.model tiny, C
.data
sX db 'Enter x: $' ;приглашения для ввода
sA db 0ah,'Enter a: $'
sY db 0ah,'Y = $' ;результат
sAny db 0dh,0ah,'Press any key$'
x dq 0 ;переменные
a dq 0
num db 32 ;буфер для ввода строки
len db 0
String db 32 dup (0)
.code
.386
.startup
lea dx, sX
mov ah, 9
int 21h ;ждем Х
lea dx, num
mov ah, 0ah
int 21h
call str2float ;преобразуем строку в double
fstp x
lea dx, sA
mov ah, 9
int 21h ;ждем А
lea dx, num
mov ah, 0ah
int 21h
call str2float ;преобразуем строку в double
fstp a
call calcY, offset a, offset x ;считаем по формуле
call float2str ;преобразуем в строку
lea dx, sY
mov ah, 9
int 21h
lea dx, String ;выведем
mov ah, 9
int 21h
lea dx, sAny
mov ah, 9
int 21h ;ждем "any key"
mov ah, 8
int 21h
mov ax, 4c00h
int 21h
;експонента st=e^st
exp proc
fldl2e ;log(осн 2)e->st
fmulp ;st(1)*log(осн 2)e->st
fld st ;x*log[2]e->st(1)
frndint ;округляем st до целого
fsub st(1),st ;st(1)-=st
fxch ;st(1)<->st
f2xm1 ;st=(2 в степени st) - 1
fld1 ;1->st
fadd ;st+=1
fscale ;exp = st * (2 в степени st(1))
fstp st(1) ;чтобы убрать значение из st(1)
ret
exp endp
;считаем по формуле
y=(3*4+5*6-ae^x)/(7/2+4/3+12/3)*(16/2)*3*6*cos(a/x)
calcY proc pa:word, px:word
local c2:word, c3:word, c4:word, c5:word, c6:word, c7:word, c12:word, c16:word
uses di, si
mov di, pa ;адрес А
mov si, px ;адрес Х
mov c2, 2 ;константы
mov c3, 3
mov c4, 4
mov c5, 5
mov c6, 6
mov c7, 7
mov c12, 12
mov c16, 16
fild c3 ;3
fimul c4 ;3*4
fild c5 ;5
fimul c6 ;5*6
faddp ;3*4+5*6
fld qword ptr [si] ;x
call exp ;e^x
fmul qword ptr [di] ;a*e^x
fsubp st(1), st ;3*4+5*6-a*e^x
fild c7 ;7
fidiv c2 ;7/2
fild c4 ;4
fidiv c3 ;4/3
faddp ;7/2+4/3
fild c12 ;12
fidiv c3 ;12/3
faddp ;7/2+4/3+12/3
fdivp ;y=(3*4+5*6-a*e^x)/(7/2+4/3+12/3)
fimul c16 ;y*16
fidiv c2 ;y*16/2
fimul c3 ;y*16/2*3
fimul c6 ;y*16/2*3*6
fld qword ptr [di] ;a
fdiv qword ptr [si] ;a/x
fcos ;cos(a/x)
fmulp ;y*16/2*3*6*cos(a/x)
ret
calcY endp
;Преобразование строки в вещественное число в st сопроцессора
str2float proc ;преобразование строки в вещественное число
local ww:word ;для загрузки в сопроцессор
local dcount:word ;число знаков после точки
local wSign:word ;знак числа
local c10:word ;10
fldz ;подготовим st=0
lea si, String ;числовая строка
xor ax, ax ;0
mov dcount, ax ;число знаков после точки = 0
mov wSign, ax ;положительное
mov c10, 10 ;10
s2fStart: ;цикл обхода незначащих стартовых пробелов
lodsb
cmp al, 0dh
je s2fRet ;по концу строки - выход
cmp al, ' '
je s2fStart ;на повтор
cmp al, 9
je s2fStart
cmp al, '-'
jne s2fCompare ;все остальное - на анализ
inc wSign ;по минусу - взводим признак минуса
s2fNext:
lodsb ;очередной символ
s2fCompare:
cmp al, '.' ;точка
je s2fInc
cmp al, '0'
jb s2fSign ;все, что не цифры - конец числа
cmp al, '9'
ja s2fSign
and ax, 0fh ;иначе готовим разряд
mov ww, ax ; для загрузки в сопроцессор
cmp dcount, 0 ;если целая часть, то
je s2fMul10 ; на умножение на 10
mov cx, dcount ;иначе делим dcount раз на 10
fild ww ; очередной разряд
s2fdiv:
fidiv c10 ;делим dcount раз
loop s2fdiv
faddp ;складываем разряд за точкой с формируемым числом
s2fInc:
inc dcount ;для точки только увеличиваем dcount
jmp s2fNext ;пока не дойдем до конца
s2fMul10: ;целое число
fimul c10 ;умножаем старое на 10
fiadd ww ;и прибавляем очередной разряд
jmp s2fNext
s2fSign:
cmp wSign, 0 ;если bSign == 1
je s2fRet
fchs ;то меняем знак
s2fRet:
ret
str2float endp
;преобразование вещественного числа из st в строку по адресу String
float2str proc
local c10:word ;10
local wSign:word ;знак
local dig:word ;буфер для извлечения целого из сопроцессора
local sTemp:byte:64 ;временный буфер для строки
mov c10, 10 ;10
mov wSign, 0 ;пока считаем, что положительное
lea di, sTemp ;здесь будем формировать строку
ftst ;Проверяем число
fstsw ax ;флаги в ax
sahf ;флаги в регистре флагов
jnz f2s_notZero ;не 0
mov ax, '$0' ;если 0, то выводим 0
stosw
jmp f2s_Ret ;на выход
f2s_notZero: ;не 0
jnc f2s_1 ;если отрицательное,
inc wSign ; то помечаем минус
fchs ; и оставляем модуль числа.
; Пояснение далее пойдёт на примере. ; ST(0) ST(1) ST(2) ST(3) ...
; Отделим целую часть от дробной. ; 73.25 ...
f2s_1: 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], '$'
; и скопировать в буфер String
lea si, sTemp
lea di, String
xor cx, cx ;длина
cmp wSign, 0 ;проверим на знак
je f2s_6
mov al, '-' ;отрицательное
stosb
f2s_6:
lodsb
stosb ;копируем 1 байт
inc cx ;считаем
cmp cx, 14 ;копируем только 14 байт !!! (если получится число
; с большим чем 14 байт знаков, то последние усекутся)
je f2s_7 ;насильно закрываем $!
cmp al, '$'
jne f2s_6 ;копирование завершаем по $
dec cx ;отнимем 1 (посчитался $)
f2s_7:
mov byte ptr [di], '$' ;закроем $ (для случая обрезания)
f2s_Ret:
ret
float2str endp
end
Если Вы уже зарегистрированы на Портале - войдите в систему, если Вы еще не регистрировались - пройдите простую процедуру регистрации.