Консультация № 189210
17.04.2016, 14:41
0.00 руб.
0 4 1
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:

Нужно написать программу для TASM

Рассчитать и вывести значения выражения,при заданных пользователем значения x и a.

Y=3*6+4*4/(sin(a)*3)*(48+16/2)*(5+8*cos(x)/14-3)

Обсуждение

давно
Посетитель
7438
7205
17.04.2016, 15:24
общий
Адресаты:
Если используются sin и cos, то используются вещественные числа?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
400202
2
17.04.2016, 23:22
общий
Да
давно
Посетитель
400202
2
17.04.2016, 23:22
общий
Адресаты:
Да
давно
Посетитель
7438
7205
18.04.2016, 18:41
общий
это ответ
Здравствуйте, DRAGUN!
Программа работает с вещественными числами, считает в сопроцессоре
[code lang=asm h=200]
.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
[/code]
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа