Консультация # 189164: Уважаемые эксперты! Прошу вас помочь с составлением программы для CompModel. Разность сумм четных и нечетных элементов массива; 11. Заранее - большое спасибо! ...Консультация # 189210: Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос: Нужно написать программу
для TASM Рассчитать и вывести значения выражения,при заданных пользователем значения x и a. Y=3*6+4*4/(sin(a)*3)*(48+16/2)*(5+8*cos(x)/14-3) ...
Уважаемые эксперты! Прошу вас помочь с составлением программы для CompModel. Разность сумм четных и нечетных элементов массива; 11. Заранее - большое спасибо!
RD #40 ;стартовый адрес массива
WR R0 ;в регистре R0
RD #10 ;количество
WR R1 ;в R1
RD #0 ;сумма
WR R2 ;четных
WR R3 ;нечетных
LOOP:RD @R0+ ;читаем очередного, с автоинкрементом адреса
WR R4 ;сохраним в R4
DIV #2 ;вот тут самое "хитрое" место: так как нет ни команд сдвига, ни логических
MUL #2 ;то пришлось разделить на 2, потом умножить на 2 и результат сравнить с исходным
SUB R4 ;если не равны, то нечетное!
JNZ ODD;нечетное
RD R4 ;четное
ADD R2 ;накапливаем сумму четных
WR R2
JMP NEXT ;на продолжение цикла
ODD:RD R4;нечетное
ADD R3 ;накапливаем сумму
WR R3
NEXT:JRNZ R1,LOOP ;повторяем R1 раз
RD R2 ;сумма четных
SUB R3 ;минус сумма нечетных
OUT
HLT
Консультировал: Лысков Игорь Витальевич (Старший модератор)
Дата отправки: 19.04.2016, 00:03
.model small
.data
sEnterA db "Enter a = $" ;приглашение ввести а
sEnterX db "Enter x = $" ;приглашение ввести х
sY db "y = $" ;вывод y
c10 dw 10 ; 10 основание системы счисления
;числа-константы из формулы
c3 dw 3
c6 dw 6
c4 dw 4
c48 dw 48
c16 dw 16
c2 dw 2
c5 dw 5
c8 dw 8
c14 dw 14
;буфер для ввода строки-вещественного числа
max db 64 ;размер буфера
len db ? ;реальная длина
String db 64 dup (?) ;сама строка
sTemp db 64 dup(?) ;временный буфер для формирования строки-числа
dig dw ? ;цифра при обмене с сопроцессором
a dd ? ;числа, которые вводятся
x dd ?
.code ;сегмент кода
.386 ;необходимо для команды fsin и fcos
.startup ;инициализация сегментов для выбранной модели памяти
lea dx, sEnterA
call InputFloat ;вводим a
fstp a ;сохраним из стека сопроцессора в переменной а
lea dx, sEnterX
call InputFloat ;вводим x
fstp x
lea dx, sY ;выведем строку "y = "
mov ah, 9
int 21h
call CalcY ;считаем y по формуле, результат в стеке сопроцессора
call float2str ;преобразуем вещ число в стеке сопроцессора в строку
lea dx, String ;и выведем
mov ah, 9
int 21h
mov ah, 0 ;ждем нажатие на клавишу
int 16h
.exit 0
CalcY proc ;расчет по формуле
fild C3 ;3
fimul C6 ;3*6
fild C4 ;4
fimul C4 ;4*4
fld a ;a
fsin ;sin(a)
fimul C3 ;sin(a)*3
fdivp ;4*4/sin(a)*3
fild C48 ;48
fild C16 ;16
fidiv C2 ;16/2
faddp ;48+16/2
fmulp ;(4*4/sin(a)*3)(48+16/2)
fild C5 ;5
fld x ;x
fcos ;cos(x)
fimul C8 ;8cos(x)
fidiv C14 ;8cos(x)/14
faddp ;5+(8cos(x)/14)
fisub C3 ;5+(8cos(x)/14)-3
fmulp ;(4*4/sin(a)*3)(48+16/2)(5+(8cos(x)/14)-3)
faddp ;3*6 + (4*4/sin(a)*3)(48+16/2)(5+(8cos(x)/14)-3)
ret
CalcY endp
InputFloat proc ;ввод вещественного числа
push dx ;сохраним адрес приглашения для повторного ввода
mov ah, 9 ;выведем строку приглашения
int 21h
lea dx, max ;вводим строку
mov ah, 0ah
int 21h
lea si, String ;адрес строки
call str2float ;преобразовываем во float с проверкой синтаксиса
pushf ;флаг С говорит о корректности строки, сохраним флажки
mov ah, 2
mov dl, 0dh ;перевод на новую строку
int 21h
mov dl, 0ah
int 21h
popf ;восстановим флажки
pop dx ;восстановим (уберем из стека) адрес приглашения
jc InputFloat ;ошибка - на повтор ввода!
ret ;введенное число в стеке сопроцессора
InputFloat endp
;Преобразование строки в вещественное число в st сопроцессора
str2float proc ;преобразование строки в вещественное число
fldz ;подготовим st=0
xor dx, dx ;число знаков после точки = 0
xor bx, bx ;bl = 0/1 знак числа +/-, bh = 1/0 знак уже введен/не задан
xor di, di ;число введенных цифр, для контроля позиции знака
s2fNext:
lodsb ;очередной символ
cmp al, 0dh ;дошли до конца?
je s2fSign ;учтем знак
cmp al, '+' ;плюс?
jne s2f_minus
cmp bh, 0 ;знак уже был введен?
jne s2f_err ;можно только раз
test di, di
jne s2f_err ;знак можно писать только в первой позиции
mov bh, 1 ;знак задан
jmp s2fNext
s2f_minus:
cmp al, '-' ;минус?
jne s2f_point
cmp bh, 0 ;знак уже был введен?
jne s2f_err ;можно только раз
test di, di
jne s2f_err ;знак можно писать только в первой позиции
mov bx, 0101h ;задаем знак - минус
jmp s2fNext
s2f_point:
cmp al, '.' ;точка
jne s2f_digit
test dx, dx ;точку можно задать только один раз
jne s2f_err
jmp s2fInc
s2f_digit: ;проверка на цифры
cmp al, '0'
jb s2f_err
cmp al, '9'
ja s2f_err
inc di ;есть цифра
and ax, 0fh ;готовим разряд
mov dig, ax ; для загрузки в сопроцессор
test dx, dx ;если целая часть, то
je s2fMul10 ; на умножение на 10
mov cx, dx ;иначе делим dx раз на 10
fild dig ; очередной разряд
s2fdiv:
fidiv c10 ;делим dх раз
loop s2fdiv
faddp ;складываем разряд за точкой с формируемым числом
s2fInc:
inc dx ;для точки только увеличиваем dх
jmp s2fNext ;пока не дойдем до конца
s2fMul10: ;целое число
fimul c10 ;умножаем старое на 10
fiadd dig ;и прибавляем очередной разряд
jmp s2fNext
s2fSign: ;ввод числа закончен, учтем знак
cmp bl, 0 ;если -
je s2fRet
fchs ;то меняем знак
s2fRet:
clc ;все ок
ret
s2f_err:
stc ;ошибочка
fstp st ;выкидаем из стека число
ret
str2float endp
;преобразование вещественного числа из st в строку по адресу String
float2str proc
push es
push ds
pop es ;es=ds
lea di, sTemp ;здесь будем формировать строку
ftst ;Проверяем число
fstsw ax ;флаги в ax
sahf ;флаги в регистре флагов
jnz f2s_notZero ;не 0
mov dx, 1 ;длина 1
mov bl, 0 ;сбрасываем знак
mov ax, '0' ;если 0, то выводим 0
stosw
jmp f2s_Ret ;на выход
f2s_notZero: ;не 0
mov al, ' ' ; пока считаем, что положительное
jnc f2s_sign ;если оно отрицательное,
mov al, '-' ; то минус
fchs ; и оставляем модуль числа.
f2s_sign:
stosb ;знак числа
; Пояснение далее пойдёт на примере. ; ST(0) ST(1) ST(2) ST(3) ...
; Отделим целую часть от дробной. ; 73.25 ... что-то не наше
fld1 ; 1 73.25 ...
fld st(1) ; 73.25 1 73.25 ...
; Остаток от деления на единицу даст дробную часть.
fprem ; 0.25 1 73.25 ...
; Если вычесть её из исходного числа, получится целая часть.
fsub st(2), st ; 0.25 1 73 ...
fxch st(2) ; 73 1 0.25 ...
; Сначала поработаем с целой частью. Считать количество цифр будем в CX.
xor cx, cx
; Поделим целую часть на десять,
f2s_2: fidiv c10 ; 7.3 1 0.25 ...
fxch st(1) ; 1 7.3 0.25 ...
fld st(1) ; 7.3 1 7.3 0.25 ...
; отделим дробную часть - очередную справа цифру целой части исходного числа,-
fprem ; 0.3 1 7.3 0.25 ...
; от чатсного оставим только целую часть
fsub st(2), st ; 0.3 1 7 0.25 ...
; и сохраним цифру
fimul c10 ; 3 1 7 0.25 ...
fistp dig ; 1 7 0.25 ...
inc cx
; в стеке.
push dig
fxch st(1) ; 7 1 0.25 ...
; Так будем повторять, пока от целой части не останется ноль.
ftst
fstsw ax
sahf
jnz f2s_2
; Теперь выведем её.
f2s_3: pop ax
; Вытаскиваем очередную цифру, переводим её в символ и выводим.
add al, 30h
stosb
; И так, пока не выведем все цифры.
loop f2s_3 ; 0 1 0.25 ...
; Итак, теперь возьмёмся за дробную часть, для начала проверив её существование.
fstp st(0) ; 1 0.25 ...
fxch st(1) ; 0.25 1 ...
ftst
fstsw ax
sahf
jz f2s_5
; Если она всё-таки ненулевая, выведем точку
lea ax, sTemp
mov cx, di
sub cx, ax
sub cx, 63
neg cx
mov al, '.'
stosb
; Помножим дробную часть на десять
f2s_4: fimul c10 ; 2.5 1 ...
fxch st(1) ; 1 2.5 ...
fld st(1) ; 2.5 1 2.5 ...
; отделим целую часть - очередную слева цифру дробной части исходного числа,-
fprem ; 0.5 1 2.5 ...
; оставим от произведения лишь дробную часть
fsub st(2), st ; 0.5 1 2 ...
fxch st(2) ; 2 1 0.5 ...
; сохраним полученную цифру во временной ячейке
fistp dig ; 1 0.5 ...
; и сразу выведем.
mov ax, dig
add al, 30h
stosb
; Теперь, если остаток дробной части ненулевой
fxch st(1) ; 0.5 1 ...
ftst
fstsw ax
sahf
; и мы вывели менее cx цифр, продолжим
loopnz f2s_4 ; 0 1 ...
; Итак, число выведено. Осталось убрать мусор из стека.
f2s_5: fstp st(0) ; 1 ...
fstp st(0) ; ...
mov byte ptr [di], '$' ;закроем строку знаком '$' для функции 9
; и скопировать в буфер String не более 14 знаков
lea si, sTemp
lea di, String
mov dx, 0 ;длина
f2s_6:
lodsb
stosb ;копируем 1 байт
inc dx ;считаем
cmp dx, 14 ;копируем только 14 байт !!! (если получится число
; с большим чем 14 байт знаков, то последние усекутся)
je f2s_7 ;насильно закрываем '$'!
cmp al, '$'
jne f2s_6 ;копирование завершаем по '$'
dec dx ;отнимем 1 (посчитался байт '$')
f2s_7:
mov byte ptr [di], '$' ;закроем '$' (для случая обрезания)
f2s_Ret:
pop es
ret
float2str endp
end
Консультировал: Лысков Игорь Витальевич (Старший модератор)
Дата отправки: 18.04.2016, 18:41
Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались.
Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора -
для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение.
Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал,
который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом.
Заходите - у нас интересно!