Написание программы для вычисления заданного выражения с помощью TASM
Основные способы передачи аргументов. Ввод значений исходных данных и вывод результата на экран. Возможные ошибки при вводе чисел с клавиатуры. Получение флагов после применения операции сравнения. Вывод вещественного числа в экспоненциальной форме.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 23.06.2012 |
Размер файла | 267,7 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Размещено на http://www.allbest.ru/
Государственное образовательное учреждение высшего профессионального образования
Белгородский Государственный Технологический Университет им В.Г.Шухова.
Кафедра программного обеспечения вычислительной техники и
автоматизированных систем
Курсовой проект
по дисциплине «Организация ЭВМ и систем»
Выполнил:
ст.гр. ПВ-22
Жадан А.П.
Проверил:
Гарибов А.И.
Белгород 2012
СОДЕРЖАНИЕ
Постановка задачи
Спецификации подпрограмм
Исходный код (с подробными комментариями)
Пример выполнения программы
Постановка задачи
Написать программу для вычисления заданного выражения с помощью TASM. Каждую функцию реализовать в виде отдельной подпрограммы, используя наиболее подходящий способ передачи аргументов. Вычисления, которые встречаются несколько раз, оформить в виде макрокоманд. Организовать ввод значений исходных данных и вывод результата на экран. Обработать возможные ошибки при вводе чисел с клавиатуры. Все числа считать вещественными, которые могут представляться в форме с плавающей точкой.
Выражения:
Спецификации подпрограмм
1) getA proc
вычисляет значение выражения A
входные данные: ячейки памяти x,y,z
выходные данные: ячейки памяти a, ra
2) getB proc
вычисляет значение выражения B
входные данные: ячейки памяти x,y,z
выходные данные: ячейки памяти b, rb
3) chislitel proc
вычисляет значение числителя выражений A и B
входные данные: ячейки памяти x,y
выходные данные: значение в st(0) , значение в регистре AX = 0 - вычисление прошло успешно или 1 - произошла ошибка при попытке вычислить
4) logarifm proc
вычисляет значение куба натурального логарифма от z/2
входные данные: ячейка памяти z
выходные данные: значение в st(0), значение в регистре AX = 0 - вычисление прошло успешно или 1 - произошла ошибка при попытке вычислить
outpint proc
осуществляет вывод целого числа со знаком
входные данные: значение в st(0)
выходные данные: нет
5) inpint proc
осуществляет ввод целого числа со знаком
входные данные: нет
выходные данные: значение в st(0)
6) inexp proc
осуществляет ввод вещественного числа со знаком в экспоненциальной форме
входные данные: нет
выходные данные: значение в st(0)
7) outfloat proc
осуществляет вывод вещественного числа со знаком
входные данные: значение в st(0)
выходные данные: нет
8) outexp proc
осуществляет вывод вещественного числа со знаком в экспоненциальной форме
входные данные: значение в st(0)
выходные данные: нет
9) splitnumber proc
получить дробную(без знака) и целую части числа
входные данные: значение в st(0)
выходные данные: st(0) - модуль дробной части, st(1) - целая часть (со знаком)
10) pow proc
возвести число в степень
входные данные: значение в st(0) - степень, значение в st(1) - база
выходные данные: st(0) - вычисленное значение, значение в стеке 0 - вычисление прошло успешно или 1 - произошла ошибка при попытке вычислить
Исходный код программы
crsr_wrk.asm
masm
outstr macro str_out ;;1) вывод строки str_out на дисплей
lea dx, str_out
mov ah, 09h
int 21h
endm
inputnum macro dest ;;2) ввод числа num с клавиатуры в ячейку памяти dest
call inexp
fstp dest
endm
outputnum macro src ;;3) вывод числа num на дисплей из ячейки памяти src
fld src
call outexp
endm
get_flags macro ;;4) получение флагов после применения операции сравнения
fstsw ax
sahf
endm
getconst macro ;;5)получение 1,7 в вершине стеке сопроцессора
mov rb, 17
fild rb
mov rb, 10
fild rb
fdiv
endm
stk segment stack
db 256 dup (0)
stk ends
data segment 'data'
in_xstr db "ENTER X:",'$'
in_ystr db "ENTER Y:",'$'
in_zstr db "ENTER Z:",'$'
err_str db "INVALID VALUE",'$'
out_a db "A = ",'$'
out_b db "B = ",'$'
jump db 10,13,'$'
x dd 0 ;;исходные значения
y dd 0
z dd 0
a dd 0 ;;вычисленные значения
b dd 0
ra dw 0 ;;флаги успеха вычислений соотв величин
rb dw 0
data ends
code segment 'code'
;==точка входа
main proc
assume cs:code,ds:data,ss:stk
mov ax, data
mov ds, ax
.386
finit
;==ввод значений
outstr in_xstr
inputnum x
outstr in_ystr
inputnum y
outstr in_zstr
inputnum z
call getA
call getB
xor ax, ax
xor bx, bx
;;Вывод значения a
outstr out_a
mov ax, ra
cmp ax, bx
je @out_a_value
outstr err_str
jmp @_next_
@out_a_value:
outputnum a
;;вывод значения b
@_next_:
outstr jump
outstr out_b
mov ax, rb
cmp ax, bx
je @out_b_value
outstr err_str
jmp @exit_prog
@out_b_value:
outputnum b
;;выход
@exit_prog:
mov ax, 4c00h
int 21h
main endp
;==вычисление A
getA proc
pusha
call chislitel ;; st0: chisl
xor bx, bx
cmp ax, bx
je @get_znama
mov ra, 1
fstp st(0)
jmp @exit_asub
@get_znama:
call logarifm ;; st(0): ln st(1): chisl
cmp ax, bx
je @get_znama_
mov ra, 1
fstp st(0)
fstp st(0)
jmp @exit_asub
@get_znama_:
fabs
getconst ;; st(0): 1,7 st(1): ln st(2): chisl
fadd
fdiv ;; st(0): a
mov byte ptr ra, 0
fstp a ;; fpu: <empty>
@exit_asub:
popa
ret
getA endp
;==вычисление B
getB proc
pusha
call chislitel ;; st0: chisl
xor bx, bx
cmp ax, bx
je @get_znam2
mov rb, 1
fstp st(0)
jmp @exit_bsub
@get_znam2:
call logarifm ;; st0: ln st1: chisl
cmp ax, bx
je @get_znam2_
mov rb, 1
fstp st(0)
fstp st(0)
jmp @exit_bsub
@get_znam2_:
fadd st(0), st(0)
ftst ;;тут может быть 0, обработаем это
get_flags
jnz @gogo
fstp st(0)
fstp st(0)
mov ax, 1
jmp @exit_bsub
@gogo:
fdiv
mov rb, 0
fstp b
@exit_bsub:
popa
ret
getB endp
;;процедура, вычисляющая числители чисел a и b
;;на вход - инициализированные значения параметров x,y,z
;;на выход - значение числителя на вершине стека сопроцессора
;; в регистре AX - успех выполнения операции
chislitel proc
fld x ;;st(0): x
fld1 ;;st(0): 1 st(1): x
fld1
fadd st(0), st(0) ;;st(0): 2 st(1): 1 st(2): x
fadd st(0), st(1) ;;st(0): 3 st(1): 1 st(2): x
fdiv ;;st(0): 1/3 st(1): x
call pow ;;st(0): x^(1/3) <если x>0> в стеке - успех вычислений
pop ax
mov bx, 0
cmp ax, bx
jne @endm_1
;;st(0): x^(1/3)
fld y
fld y
fld y
fadd
fadd ;;st(0): 3y st(1): x^(1/3)
fsin ;;st(0): sin(3y) st(1): x^(1/3)
fadd st(0), st(0) ;;st(0): 2sin(3y) st(1): x^(1/3)
fsub ;;st(0): chisl
@endm_1:
ret
endp
;;процедура, вычисляющая ln^3(z/2)
;;результат выполнения - в стеке сопроцессора
;;успех выполнения - в регистре AX
logarifm proc
fld z
ftst
get_flags
ja @contm2
mov ax, 1
jmp @endm_2
@contm2:
fld1
fadd st(0), st(0) ;;st(0): 2 st(1): z
fdiv ;;st(0): z/2
fld1 ;;st0 = 1; st1 = z/2
fxch ;;st0 = z/2; st1 = 1
fyl2x ;;st0 = log2(z/2)
fldl2e ;;st0 = log2(e); st1 = log2(z/2)
fdiv ;;st0 = log2(z/2) / log2(e) ; ln(z/2)
fld st(0) ;;st0 = ln(z/2); st1 = ln(z/2)
fmul st(0), st(0) ;;st0 = ln^2(z/2); st1 = ln(z/2)
fmul ;;st0 = ln^3(z/2)
mov ax, 0
@endm_2:
ret
endp
;;==вывод целого числа со знаком
outpint proc
push cx
push dx
push bx
push ax
; Проверяем число на знак.
test ax, ax
; Если оно отрицательное, выведем минус и оставим его модуль.
jns short @op0
mov ah, 02h
mov dl, '-'
int 21h
pop ax
push ax
neg ax
; Если положительное - плюс
jmp short @op1
@op0: mov ah, 02h
mov dl, '+'
int 21h
pop ax
push ax
; Количество цифр будем держать в CX.
@op1: xor cx, cx
mov bx, 10
@op2: xor dx, dx
div bx
; Делим число на десять. В остатке получается последняя цифра.
; Сразу выводить её нельзя, поэтому сохраним её в стеке.
push dx
inc cx
; А с частным повторяем то же самое, отделяя от него очередную
; цифру справа, пока не останется ноль, что значит, что дальше
; слева только нули.
test ax, ax
jnz short @op2
; Теперь приступим к выводу.
mov ah, 02h
@op3: pop dx
; Извлекаем очередную цифру, переводим её в символ и выводим.
add dl, 30h
int 21h
; Повторим ровно столько раз, сколько цифр насчитали.
loop @op3
pop ax
pop bx
pop dx
pop cx
ret
outpint endp
;==Ввод целого числа со знаком
inpint proc far
push cx
push dx
push bx
push si
; В SI будет признак знака, в BX - число, CX тоже пригодится.
xor si, si
xor bx, bx
xor cx, cx
; Введём первый символ.
mov ah, 01h
int 21h
; Здесь и только здесь может попасться знак. Если это не так,
; перейдём к обычной обработке символа.
cmp al, '+'
je short @ip0
cmp al, '-'
jne short @ip1
; Иначе установим признак знака и
inc si
; введём следующий символ.
@ip0: mov ah, 01h
int 21h
; Если символ за '9', то ввод некорректный, прекратим этот беспредел.
@ip1: cmp al, 39h
ja short @ip2
; Переводим символ в число. Если при этом получится нечто отрицательное,
; то исходный символ перед '0', значит, ввод можно прерывать.
sub al, 30h
jb short @ip2
; Итак, в AL цифра, которую нужно приписать справа к уже имеющемуся
; в BX числу. Поместим цифру из AL в CX. Именно для этого он обнулялся.
mov cl, al
; Умножим текущий результат на 10.
shl bx, 1 ; BX = 2 * bx
mov ax, bx ; AX = 2 * bx
shl ax, 2 ; AX = 8 * bx
add bx, ax ; BX = 10 * bx
add bx, cx ; BX = 10 * bx + al
; И так, пока вводят цифры.
jmp short @ip0
; Когда ввели нецифру, посмотрим, надо ли менять знак,
@ip2: test si, si
jz short @ip3
neg bx
; перейдём на новую строку
@ip3: mov ah, 02h
mov dl, 0Dh
int 21h
; и запишем результат в AX.
mov dl, 0Ah
int 21h
mov ax, bx
pop si
pop bx
pop dx
pop cx
ret
inpint endp
;==ввод вещественного числа в экспоненциальной форме
inexp proc far
push ax
push dx
push si
; Формируем кадр стека для хранения десятки и ещё чего-нибудь целого.
push bp
mov bp, sp
push 10
push 0
; В SI будет признак знака.
xor si, si
; А здесь будет накапливаться число.
fldz
; Вводим первый символ.
mov ah, 01h
int 21h
; Он может оказаться плюсом, что ни на что не повлияет,
; поэтому просто перейдём к следующему символу.
cmp al, '+'
je short @ie0
; Если это и не минус, то перейдём к дальнейшей обработке.
cmp al, '-'
jne short @ie1
; Если всё же минус, запомним
inc si
; и введём следующий символ.
@ie0: mov ah, 01h
int 21h
; Если хотят ввести экспоненту, закончим ввод мантиссы.
@ie1: cmp al, 'e'
je short @ie7
cmp al, 'E'
je short @ie7
; Может быть, надо перейти к вводу дробной части.
cmp al, '.'
je short @ie2
; А, может, ввели цифру. Если нет, прервём ввод.
cmp al, 39h
ja short @ie5
sub al, 30h
jb short @ie5
; Иначе приписываем эту цифру к текущему результату,
mov [bp - 4], al
; домножая его на десять
fimul word ptr [bp - 2]
; и прибавляя эту цифру.
fiadd word ptr [bp - 4]
jmp short @ie0
; Итак, если надо вводить дробную часть, запасёмся единицей
; для формирования отрицательных степеней десятки.
@ie2: fld1
; Вводим очередной символ.
@ie3: mov ah, 01h
int 21h
; Возможно, нужно перейти к вводу экспоненты.
cmp al, 'e'
je short @ie8
cmp al, 'E'
je short @ie8
; Возможно, введут цифру. Если нет, прервём ввод.
cmp al, 39h
ja short @ie4
sub al, 30h
jb short @ie4
mov [bp - 4], al
; Получим очередную степень десятки,
fidiv word ptr [bp - 2]
; продублируем её,
fld st(0)
; помножим на введённую цифру, получив очередной разряд,
fimul word ptr [bp - 4]
; и добавим к текущему результату.
faddp st(2), st
jmp short @ie3
; После ввода мантиссы удалим более ненужную
; степень десятки
@ie4: fstp st(0)
; и пойдём поближе к выходу.
jmp short @ie5
; Если от мантиссы переходим к экспоненте,
; опять-таки очистим степень десятки
@ie8: fstp st(0)
; и введём экспоненту.
@ie7: call inpint
; Теперь текущий результат надо домножить
; на десятку в введённой степени.
mov [bp - 4], ax
fild word ptr [bp - 4]
; Возьмём логарифм десятки,
fldl2t
; домножим на требуемую степень,
fmulp st(1), st
; разобьём её на целую и дробную части,
fld1
fld st(1)
fprem
fsub st(2), st
; сначала возведём двойку в дробную часть,
f2xm1
faddp st(1), st
; а затем и в целую.
fscale
fstp st(1)
; Домножаем на текущий результат.
fmulp st(1), st
; Итак, получили на вершине стека введённое число.
; Перейдём на новую строку
@ie5: mov ah, 02h
mov dl, 0Dh
int 21h
mov dl, 0Ah
int 21h
; и вспомним про знак.
test si, si
jz short @ie6
fchs
@ie6: leave
pop si
pop dx
pop ax
ret
inexp endp
;==вывод вещественного числа
outfloat proc
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
;==вывод вещественного числа в экспоненциальной форме
outexp proc
push ax
push bp
mov bp, sp
push 10
push 0
; Разобьём число на двоичные мантиссу и экспоненту.
; Но если исходное число - ноль, в качестве
; экспоненты мы получим минус бесконечность.
; Так что этот случай рассмотрим отдельно.
ftst
fstsw ax
sahf
jnz short @oe0
mov ah, 02h
mov dl, 30h
int 21h
jmp short @oe2
; Итак, получаем двоичные мантиссу и экспоненту.
@oe0: fxtract
; Переведём экспоненту в десятичную. Для этого
; домножим её на lg 2
fldlg2
fmulp st(2), st
; и округлим,
fld st(1)
frndint
; вычислив сделанную поправку.
fsub st(2), st
; Экспоненту получили. Теперь возьмёмся за мантиссу.
fistp word ptr [bp - 4]
; Для начала внесём поправку, полученную
; при округлении экспоненты.
fxch st(1)
; Для этого нужно возвести десятку в вычисленную
; поправку. В общем случае возведение в степень (p^q)
; начинается с получения двоичного логарифма
; основания (log p), то есть, например, так:
; fld1
; fld основание
; fyl2x
; Но в нашем случае двоичный логарифм десяти
; можно загрузить непосредственно.
fldl2t
; Теперь домножим его на показатель степени. (q log p)
fmulp st(1), st
; Осталось возвести в это двойку (2 ^ (q log p) = p ^ q).
; Сразу пользоваться f2xm1 нельзя - она требует операнд
; в диапазоне -1..1. Ну, что ж, отделим дробную часть
; нужной степени
fld1
fld st(1)
fprem
; и оставим в сторонке целую.
fsub st(2), st
; В дробную степень возведём двойку.
f2xm1
faddp st(1), st
; Теперь домножим это на целую степень двойки
fscale
; и удалим мусор.
fstp st(1)
; Наконец, внесём поправку в двоичную мантиссу.
fmulp st(1), st
; Теперь приведём её к диапазону 1..10, она ведь
; вполне может оказаться меньше единицы. Сравним,
fld1
fcomp st(1)
fstsw ax
sahf
jbe short @oe1
; если действительно меньше, подправим за счёт экспоненты.
fimul word ptr [bp - 2]
dec word ptr [bp - 4]
; Теперь можно вывести мантиссу
@oe1: call outfloat
; и экспоненту.
mov ah, 02h
mov dl, 'e'
int 21h
mov ax, word ptr [bp - 4]
call outpint
@oe2: leave
pop ax
ret
outexp endp
;получить дробную(без знака) и целую части числа
;на вход - st(0) - число
;на выход - st(0) - дробная часть (без знака) st(1) - целая часть (со знаком)
splitnumber proc
pusha
;;инициализация локальных переменных
enter 2, 0
;;настраиваем стек на нужную нам режим округления
fstsw ax ;;грузим в ax тек состояние регистра cwr
mov cx, ax ;;сохраняем его копию
or ax, 110000100000b ;; cwr.rc = 11b => отброс дробной части
mov word[bp-2], ax ;;приходится так, fldcw не читает с регистров..
fldcw word[bp-2] ;;..а только с памяти
;;получаем целую часть модуля числа
;; st(0) = number
fld st(0) ;; st(0) = number st(1) = number
fabs ;; st(0) = |number| st(1) = number
frndint ;; st(0) = int(|number|), st(1) = number
;;восстанавливаем старый режим округления
or cx, 00100000b ;;при PE=0 немаскируемое исключение валит всю программу, собака.
mov word[bp-2], cx
fldcw word[bp-2]
;; st(0) = int(|number|), st(1) = number
fxch ;; st(0) = number, st(1) = int(|number|)
ftst
get_flags
jc @negative
;;number >= 0
;; st(0) = int(|number|), st(1) = number
fld st(1) ;; st(0) = int(|number|) st(1) = number st(2) = int(|number|)
fsub ;; st(0) = float(|number|) st(1) == int(|number|)
jmp @exit_
@negative: ;; number < 0
;; st(0) = number, st(1) = int(|number|)
fxch
fld st(1) ;; st(0) = number st(1) = int(|number|), st(2) = number
fabs ;; st(0) = |number| st(1) = int(|number|), st(2) = number
fxch
fsub ;; st(0) = float(|number|) st(1) = number
fxch ;; st(0) = number st(1) = float(|number|)
fld st(1) ;; st(0) = float(|number|) st(1) = number st(2) = float(|number|)
fadd ;; st(0) = int(number) st(1) = float(|number|)
fxch ;; st(0) = float(|number|) st(1) = int(number)
@exit_:
;;выходим
leave
popa
ret
endp
;;возвести число в произвольную степень
;;на вход - st(0) - степень (p), st(1) - база (b)
;;выход - st(0) - результат (r), если результат вычислим
;; - в стеке - успех операции: 0 - все прошло успешно 1 - ошибка при попытке вычисления
;; алгоритм на псевдокоде
;;b^p = 2^(p*lb(b)) b>0
;;bx- нечетность степени, если она целая, dx- знак степени
;;--
;;p=0? => {ret 1}
;;p<0? => {dx=1; p = abs(p); }else{dx=0}
;;b=0? => {ret 0}
;;b<0?{
;; float(|p|)=0?=>{
;; (p mod 2)=1? bx=1 else bx=0
;; b=abs(b)
;; }else ret fault
;;}else bx=0
;;t = p * log2(b)
;;m = float(|t|), n = int(t)
;;sgn(m) = sgn(n)
;;r = 2^float(t) * 2^int(t)
;;bx=1? => k = -k
;;dx=1? => k = 1/k
;;ret k
pow proc
pop cx ;;адрес возврата
;;итак, st0: p, st1: b
ftst ;; p<=>0 ?
get_flags
je @ret1 ;;p==0 => ret 1
jb @AbsP ;;p<0 dx=1, p = abs(p)
mov dx, 0 ;;p>0 => dx=0
jmp @end_chk1 ;;конец обработки проверки p<=>0?
@ret1:
fstp st(0) ;;выбрасываем аргументы
fstp st(0)
fld1
jmp @succesfull
@AbsP:
mov dx, 1
fabs ;;st0: |p|, st1: b
@end_chk1:
fxch ;;st0: b, st1: |p|
ftst ;; b<=>0 ?
get_flags
je @ret0 ;; b==0 => ret 0
jb @chk2 ;; b<0, проверим вещ.часть степени
mov bx, 0 ;; b>0
jmp @end_chk2
@ret0:
fstp st(0)
fstp st(0)
fldz
jmp @succesfull
@chk2:
;;st0: b, st1: |p|
fxch ;;st0: |p|, st1: b
fld st(0) ;;st0: |p|, st1: |p|, st2: b
call splitnumber ;;st0: float(|p|), st1: int(|p|), st2:|p|, st3:b
ftst ;;st0: float(|p|)==0 ?
get_flags
fstp st(0)
fstp st(0) ;;st0: |p|, st1: b
je @floatpzero ;; float(|p|) = 0
;; float(|p|) != 0
fstp st(0) ;;очищаем аргументы
fstp st(0)
jmp @fault
@floatpzero:
;;st0: |p|, st1: b
fld st(0) ;;st0: |p|, st1: |p|, st2: b
fld1
fadd st(0), st(0)
fdiv ;;st0: |p|/2, st1: |p|, st2: b
call splitnumber ;;st0: float(|p|/2), st1: int(|p|/2), st2: |p|, st3: b
ftst ;;если вещ часть =0, то число четное
get_flags
fstp st(0)
fstp st(0) ;;st0: |p| st1: b
je @mod0
mov bx, 1
jmp @absB
@mod0:
mov bx, 0
@absB:
fxch ;;st0: b, st1: |p|
fabs ;;st0: |b|, st1: |p|
@end_chk2:
;;st0: |b|, st1: |p|
fyl2x ;;st0: |p| * log2(|b|) (далее просто t)
call splitnumber ;;st0: float(|t|), int(t)
;;компенсируем знак для float(|t|)
fxch ;;st0: int(t), st1: float(|t|)
ftst
get_flags
jb @add_sign_minus
fxch ;;st0: float(t) st1: int(t)
jmp @skip_sign_add
@add_sign_minus:
fxch ;;st0: float(|t|) st1: int(t) t<0
fchs ;;st0: float(t) st11: int(t)
@skip_sign_add:
f2xm1 ;;st0: 2^(float(t))-1 st1: int(t)
fld1
fadd ;;st0: 2^(float(t)) st1: int(t)
fxch ;;st0: int(t) st1: 2^(float(t))
fld1
fscale ;;st0: 2^(int(t)) st1: 2^(float(t))
fxch
fstp st(0)
fmul ;;st0: 2^t
mov ax, 0
cmp ax, bx
je @skipbx
fchs ;;st0: -(2^t)
@skipbx:
cmp ax, dx
je @skipdx
fld1
fdivr ;;st0: [+/-]1/(2^t)
@skipdx:
jmp @succesfull
@succesfull:
mov ax, 0
push ax
jmp @exit
@fault:
mov ax, 1
push ax
jmp @exit
@exit:
push cx
ret
endp
code ends
end main
аргумент вывод результат число
Примеры выполнения программы
Размещено на Allbest.ru
Подобные документы
Разработка ввода с клавиатуры и вывода на экран монитора данных с помощью стандартных функций printf и scanf. Ввод количества материальных точек. Работа с линейным списком. Хранение содержимого списка в блоке ячеек памяти с последовательными адресами.
курсовая работа [176,8 K], добавлен 18.01.2016Процедура ввода исходных данных в программу, вывод результатов работы программы на экран. Принцип организации хранения логически связанных наборов информации в виде файлов. Параметры характеристики файла, способы обращения к нему, соглашения по типу.
реферат [14,5 K], добавлен 06.12.2011Написание модуля на языке Ассемблер для вычисления значения выражения. Составление программы корректного ввода исходных данных в таблицу и вывода результата в виде таблицы. Создание модуля для обработки строк и программы корректного ввода исходных данных.
курсовая работа [36,8 K], добавлен 18.09.2010Приложение в среде Delphi, реализующее ввод двух целых чисел, по щелчку на кнопке с символом "=", вычисление результата операции вещественного деления с выводом значения на экран. Дополнение программы обработчика события: изменение цвета и ширины окна.
лабораторная работа [13,3 K], добавлен 15.07.2009Файловый ввод/вывод с использованием разных классов. Вызовы операционной системы. Использование вызовов операционной системы. Основные способы открытия файла. Замена файла, связанного со стандартными устройствами ввода/вывода. Операции чтения файла.
курсовая работа [1,1 M], добавлен 09.12.2016Ввод данных в ячейку из раскрывающегося списка. Проверка содержимого ячеек при вводе данных с клавиатуры. Отмена проверки значения. Таблица после подведения промежуточных итогов. Консолидация данных и порядок ее выполнения, алгоритм и основные этапы.
презентация [1,8 M], добавлен 29.09.2013Особенности работы с данными с MS Excel. Ввод данных в ячейку из раскрывающегося списка. Проверка содержимого ячеек при вводе с клавиатуры. Поиск ячеек со встроенной проверкой значений. Автоматическая обработка данных. Подведение промежуточных итогов.
презентация [1,8 M], добавлен 16.10.2013Общие сведения об алгоритмах. Свойство и этапы построения алгоритма. Нисходящее проектирование программ. Основные алгоритмические структуры. Принципы структурной алгоритмизации. Массивы случайных чисел. Ввод исходных данных. Определение и вывод данных.
методичка [435,3 K], добавлен 09.12.2014Написание программ для решения различных выражений и задач. При решении каждой задачи предусмотрены: анализ введенных с клавиатуры исходных данных, выведение условия для выхода и вывод результатов. Проиллюстрированы результаты работы каждой программы.
контрольная работа [259,8 K], добавлен 22.05.2010Описание подпрограммы SumDigit, находящей сумму цифр S целого числа N. Нахождение суммы цифр данных чисел, используя эту подпрограмму. Алгоритм и код программы, тестовые наборы. Вывод о ее работоспособности. Описание функции RingS вещественного типа.
лабораторная работа [514,5 K], добавлен 23.11.2014