Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Assembler Laba 4.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
340.99 Кб
Скачать

4.3 Пример

Пример вычисления выражения:

Анализ особенностей задачи.

Возможны две ситуации деления на ноль:

, если . Например, .

, если . Например, .

В то же время ситуация, когда , является допустимой.

.Model Small

.586

.Data

res dq 0

a dq 3.0

b dq 10.0

const25 dw 25

const4 dw 4

const5 dw 5

status dw 0

.Code

;Вывод вещественного числа

; аргумент - количество цифр дробной части

length_frac Equ [BP+4]

; локальные переменные

ten Equ word ptr [BP-2]

temp Equ word ptr [BP-4]

OutFloat Proc Near

ENTER 4, 0 ; выделим в кадре стека 4 байта под локальные переменные

MOV ten, 10

ftst ; определяем знак числа

fstsw AX

SAHF

JNC @positiv

MOV AL, '-' ; если число отрицательное - выводим минус

INT 29h

fchs ; и получаем модуль числа

@positiv:

fld1 ; загружаем единицу

fld st(1) ; копируем число на вершину стека

fprem ; выделим дробную часть

fsub st(2), st ; отнимем ее от числа - получим целую часть

fxch st(2) ; меняем местами целую и дробную части

XOR CX, CX ; обнуляем счетчик

; далее идет стандартный алгоритм вывода целого числа на экран

@1:

fidiv ten ; делим целую часть на десять

fxch st(1) ; обменяем местами st и st(1) для команды fprem

fld st(1) ; копируем результат на вершину стека

fprem ; выделим дробную часть (цифру справа от целой части)

fsub st(2), st ; получим целую часть

fimul ten ; *10

fistp temp ; получаем очередную цифру

PUSH temp ; заталкиваем ее глубже в стек

INC CX ; и увеличим счетчик

fxch st(1) ; подготовим стек к следующему шагу цикла (полученное частное на вершину, в st(1) - 1)

ftst ; проверим не получили ли в частном 0?

fstsw AX

SAHF

JNZ @1 ; нет - продолжим цикл

@2: ; извлекаем очередную цифру, переводим её в символ и выводим.

POP AX

ADD AL, '0'

INT 29h

LOOP @2

; далее то же самое, только для дробной части. Алгоритм похож на вывод целого числа, только вместо деления умножение и проход по числу слева

fstp st ; сначала проверим, есть ли дробная часть

fxch st(1)

ftst

fstsw AX

SAHF

JZ @quit ; дробная часть отсутствует

MOV AL, '.'

INT 29h ; если присутствует - выведем точку

MOV CX, length_frac ; помещаем в счетчик длину дробной части

@3:

fimul ten ; умножим на 10

fxch st(1) ; подготовка для fprem - меняем st и st(1) местами и

fld st(1) ; копируем число на вершину

fprem ; отделим дробную часть от целой

fsub st(2), st ; и оставляем дробную

fxch st(2)

fistp temp ; выталкиваем полученное число из стека в temp

MOV AX, temp ; по дробной части идем слева, значит число выводим сразу, без предварительного сохранения в стек

OR AL, 30h ; перевод в ascii

INT 29h ; на экран

fxch st(1) ; подготовим стек к следующему шагу цикла (полученное частное на вершину, в st(1) - 1)

ftst

fstsw AX

SAHF ; проверим на 0 остаток дробной части

LOOPNE @3

@quit:

fstp ; готово. Чистим стек сопроцессора

fstp st

LEAVE ; эпилог

RET 2

OutFloat EndP

func Proc Far

;PUSHA

finit ; инициализация сопроцессора

fld qword ptr[b]; b

fld qword ptr[a]; a b

fcom st(1); сравниваем a и b

fstsw status; сохраняем регистр флагов сопроцессора

MOV AH, byte ptr [status+1]

SAHF ; записываем в регистр флагов процессора

JA a_bigger; переход если a больше

JB b_bigger; переход если b больше

; если равны

fild const25; 25 a b

JMP endcalc

a_bigger: ftst; сравнение a с 0

fstsw status; сохраняем регистр флагов сопроцессора

MOV AH, byte ptr [status+1]

SAHF ; записываем в регистр флагов процессора

JE error; переход если a=0

fdivp st(1), st(0); b/a

fild const4; 4 b/a

fsubp st(1), st(0); b/a-4

JMP endcalc

b_bigger: fldz; 0 a b

fcomp st(2); сравнение b с 0

; a b

fstsw status; сохраняем регистр флагов сопроцессора

MOV AH, byte ptr [status+1]

SAHF ; записываем в регистр флагов процессора

JE error; переход если b=0

fld st(0); a a b

fmul st(1), st(0); a a*a b

fmulp st(1), st(0); a*a*a b

fild const5 ; 5 a*a*a b

fsubp st(1), st(0); a*a*a-5 b

JMP endcalc

error:

fldz; формируем результат ошибки

endcalc:

fstp res; сохранение результата

RET

func EndP

start:

MOV AX, @data

MOV DS, AX

CALL func

XOR AX,AX

XOR BX,BX

XOR CX,CX

XOR DX,DX

finit; инициализируем сопроцессор

fld res; записываем число стека для вывода

PUSH 10; заталкиваем число знаков после запятой

CALL outfloat

MOV AX,4c00h

INT 21h

End start

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]