![](/user_photo/2706_HbeT2.jpg)
Лабораторная работа 9
cos(x) * sin(x) + cos(x)^2 * sin(x)^2 + cos(x)^3 * sin(x)^3
.286c
.387
.MODEL small
.stack 100h
.data
msg db "ESC-exit",13,10,10,"cos(x) * sin(x) + cos(x)^2 * sin(x)^2 + cos(x)^3 * sin(x)^3",13,10,"Enter X (0...999) ",13,10,"$"
msg2 db "Calculating...",13,10,"$"
Pi2 DD 360 ;360 градусов
buff db 4 dup (0) ;буфер
x dw 0 ;пременная x
.code
;=========================================================
;Enter_digit - процедура ввода чисел
;=========================================================
enter_digit proc
xor si,si
xor cx,cx
xor bx,bx
@enter:
mov ah,0 ; Ожидаем нажатия и
int 16h ; читаем код клавиши
cmp al,1bh ;если esc -выход
je exit
cmp al,30h ;сравниваем в промежутке 0-9
jb @f
cmp al,40h
jnb @f
mov ah,0eh ; Выводим символ
int 10h ; на экран
mov [buff+si],al ;записать символ
inc si
inc bx
cmp bx,3 ;если равно 3,то выйти из цикла
je @f
jmp @enter
@@:
mov al,10
mov ah,0eh ; Выводим символ
int 10h ; на экран
ret
enter_digit endp
StrToHex proc
xor cx,cx
xor dx,dx
mov si,offset buff ;перевод строки из буфера в HEX
@lp1: xor ax,ax
lodsb ;берем cимвол(байт)
test al,al ;если это нулев байт, то заканчиваем
jz @ex
cmp al,'9' ;Если это не цифра, то пропускаем
jnbe @lp1
cmp al,'0' ;Если это не цифра, то пропускаем
jb @lp1
sub ax,'0' ;получаем цифровое значение
shl dx,1 ;сдвиг на 1=умножаем сумму на 2
add ax, dx ;прибавляем к ax
mov cl,2
shl dx, cl ;сдвиг на 2=умножение на 4
add dx, ax ;прибавляем текущее значение
jmp @lp1
@ex:
mov ax,dx
mov [x],ax ;результат преобразования число в x
ret
StrToHex endp
outfloat proc near
push ax
push cx
push dx
; Формируем кадр стэка, чтобы хранить в нём десятку
; и ещё какую-нибудь цифру.
push bp
mov bp, sp
push 10
push 0
; Проверяем число на знак, и если оно отрицательное,
ftst
fstsw ax
sahf
jnc @of1
; то выводим минус
mov ah, 02h
mov dl, '-'
int 21h
; и оставляем модуль числа.
fchs
; Пояснение далее пойдёт на примере. ; ST(0) ST(1) ST(2) ST(3) ...
; Отделим целую часть от дробной. ; 73.25 ... что-то не наше
@of1: 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
; Поделим целую часть на десять,
@of2: fidiv word ptr [bp - 2] ; 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 word ptr [bp - 2] ; 3 1 7 0.25 ...
fistp word ptr [bp - 4] ; 1 7 0.25 ...
inc cx
; в стэке.
push word ptr [bp - 4]
fxch st(1) ; 7 1 0.25 ...
; Так будем повторять, пока от целой части не останется ноль.
ftst
fstsw ax
sahf
jnz short @of2
; Теперь выведем её.
mov ah, 02h
@of3: pop dx
; Вытаскиваем очередную цифру, переводим её в символ и выводим.
add dl, 30h
int 21h
; И так, пока не выведем все цифры.
loop @of3 ; 0 1 0.25 ...
; Итак, теперь возьмёмся за дробную часть, для начала проверив её существование.
fstp st(0) ; 1 0.25 ...
fxch st(1) ; 0.25 1 ...
ftst
fstsw ax
sahf
jz short @of5
; Если она всё-таки ненулевая, выведем точку
mov ah, 02h
mov dl, '.'
int 21h
; и не более шести цифр дробной части.
mov cx, 6
; Помножим дрообную часть на десять,
@of4: fimul word ptr [bp - 2] ; 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 word ptr [bp - 4] ; 1 0.5 ...
; и сразу выведем.
mov ah, 02h
mov dl, [bp - 4]
add dl, 30h
int 21h
; Теперь, если остаток дробной части ненулевой
fxch st(1) ; 0.5 1 ...
ftst
fstsw ax
sahf
; и мы вывели менее шести цифр, продолжим.
loopnz @of4 ; 0 1 ...
; Итак, число выведено. Осталось убрать мусор из стэка.
@of5: fstp st(0) ; 1 ...
fstp st(0) ; ...
; Точнее, стэков.
leave
pop dx
pop cx
pop ax
ret
outfloat endp
start:
mov ax,@data ; взять адрес сегмента данных
mov ds,ax ; занести в сегментный регистр данных
mov dx,offset msg ; взять адрес строки msg
mov ah,9 ; функция 09h в AH запись строки в устройство стандартного вывода
int 21h ; вызов дос прерывания
call enter_digit
call StrToHex
mov dx,offset msg2 ; взять адрес строки msg2
mov ah,9 ; функция 09h в AH запись строки в устройство стандартного вывода
int 21h ; вызов дос прерывания
finit ;инициализация сопроцессора
FLDPI ;загрузить число Пи в st(0)
FLDPI ; и st(1)
FADD st(0),st(1) ;сложить =2Пи
fidiv Pi2 ;разделить на 360
fild x ;загрузить х как вещественное в вершину стека st(0)
fmul st(0),st(1) ;умножить x на радиан,получаем радианный угол
fsincos ;находим синус и косинус
fmul ;sin*cos
fld st(0) ;копия sin*cos результат в st(0)
fld st(0)
fmul ;st(0)=sin^2*cos^2
fld st(0)
fld st(2) ;st(1),s(0)=sin^2*cos^2
fmul ;перемножаем st(0) и st(1);st(0)=sin^3*cos^3
faddp st(1),st(0) ;складываем с выталкиванием из st(0). st(0)=sin^3*cos^3 и sin^2*cos^2
faddp st(1),st(0) ;складываем с выталкиванием из st(0). st(0)=sin^3*cos^3 + sin^2*cos^2 +sin*cos
call outfloat ;процедура вывода результата
mov ax,0C07h ; ожидание шажатия клавиши
int 21h
exit:
mov ax, 4C00h ; функция корректного выхода из программы
int 21h ;
end start