Написание программы для вычисления заданного выражения с помощью 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

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.