Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
прогр.docx
Скачиваний:
23
Добавлен:
21.12.2018
Размер:
2.58 Mб
Скачать
  1. Делит ax на 10;

  2. Результат деления записывается так: частное – в ah, остаток в al.

Пример: умножим 2*47=94d=01011110b=ax

ax/10=> ah=0000 1001, al=0000 0100

В результате после выполнения команды aam в регистрах al и ah находятся правильные двоично-десятичные цифры произведения двух цифр.

Деление

Предварительно в регистре ах необходимо получить две неупакованные BCD –цифры делимого. Далее используется команда:

AAD – коррекция делимого для представления в символьном виде.

Команда AAD:

1) Преобразует двузначное неупакованное bcd-число в регистре ах в двоичное число;

2) Полученное двоичное число используется в качестве делимого в операции деления;

3) Полученное двоичное число помещается в регистр aх.

Делимое будет двоичным числом из диапазона 0…99.

Алгоритм, по которому работает команда aad:

  1. умножается старшая цифра исходного BCD –числа в ах (содержимое ah) на 10;

  2. выполняется сложение ah+al, результат которого (двоичное число) заносится в al;

  3. обнуляется содержимое ah.

Далее необходимо использовать команду деления div для выполнения деления содержимого ах на одну BCD-цифру, находящуюся в байтовом регистре или байтовой ячейки памяти.

Например, разделим десятичное 25 на 5:

mov ax,0205h ; 25 в неупакованном формате

mov bl,5

aad ; теперь в АХ находится 19h

div bl ; АХ = 0005

Флаги SF, ZF и PF устанавливаются в соответствии с результатом, OF, AF и CF не определены.

Ah=0000 0010; al=0000 0101

1) 0000 0010 *0000 1010=0001 0100=ah

2) 0001 0100+0000 0101=0001 1001=al

3) ah=0000 0000 ; ax=0000 0000 0001 10012=2510

Упакованные BCD-числа

Сложение

Пример1:

67=0110 0111

+

75=0111 0101

=

142=1101 1100=22010 – неверный результат.

Правильный результат 0001 0100 0010 (14210)

Для корректировки результата существует команда:

DAA – коррекция результата сложения для представления в десятичном виде.

Команда daa преобразует содержимое регистра al в две упакованные десятичные цифры по следующему алгоритму:

1) если младшие четыре бита AL больше либо равно 9 или флаг AF = 1, то AL увеличивается на 6, CF устанавливается, если при этом сложении произошел перенос, и AF устанавливается в 1.

2) иначе AF = 0.

3) если теперь старшие четыре бита AL больше 9 или флаг CF = 1, то AL увеличивается на 60h и CF устанавливается в 1.

4) иначе CF = 0.

Флаги AF и CF устанавливаются, если в ходе коррекции происходил перенос из первой или второй цифры соответственно, SF, ZF и PF устанавливаются в соответствии с результатом, флаг OF не определен.

Например, если AL содержит число 19h, последовательность команд:

inc al

daa ; AL=20h (а не 1Ah, как было бы после INC).

1) 19h+1=1A

2) 1A16 =1 10102 +01102 =10 00002 =2016

Вычитание

Пример1: 67-75

67=0110 0111

+

-75=1011 0101 (75=1001011, 0110100+1=10110101=-75)

=

-8=0001 1100=28d – результат неверный.

Верный результат 0000 1000=810.

Контроль за знаком осуществляется с помощью флага cf, который фиксирует заём из старших разрядов.

Вычитание BCD-чисел осуществляется командами sub или sbb. Коррекция результата осуществляется командой:

DAS – коррекция результата вычитания для представления в десятичном виде.

Команда работает по следующему алгоритму:

1) если младшие четыре бита AL больше 9 или флаг AF = 1, то AL уменьшается на 6, CF устанавливается, если при этом вычитании произошел заем, и AF устанавливается в 1.

2) иначе AF = 0.

3) если теперь старшие четыре бита AL больше 9 или флаг CF = 1, то AL уменьшается на 60h и CF устанавливается в 1.

4) иначе CF = 0.

Пример: пусть AL содержит число 20h, тогда после команд:

dec al

das ; AL=19h (а не 1Fh, как было бы после DEC).

Пример5: Вывод на экран содержимого регистра АХ; 1 ASCII 31; 2 ASCII 32;... Под WIN32.

.386

.model flat, stdcall

includelib import32.lib

extrn ExitProcess:PROC

extrn MessageBoxA:PROC

.data

Ttl db 'Vivod na ekran',0h

Msg db 'Sodergimoe registra eax='

Msg1 db 6 dup(' ')

db 0h

C dw 65535 ;65535d=1111 1111 1111 1111

.code

start:

mov ax,C

mov si,10

mov edi,5

lp1:

xor dx,dx ;ax=FFFFh, si=000Ah, dx=0000h

div si ;FFFFh/000Ah=1999,0005h ;1999h/000Ah=028F,0003h; 028Fh/000Ah=0041,0005h; 0041h/000Ah=0006,0005h; 0006h/000Ah=0000,0006h

; AX,DX AX,DX AX,DX AX,DX AX,DX

xchg ax,dx ;Ax=0005h:Dx=1999h; Ax=0003h:Dx=028Fh Ax=0005h:Dx=0041h Ax=0005h:Dx=0006h Ax=0006h:Dx=0000h

add al,'0' ;AX=0035h Ah=00h Al=35h; Ax=0033h Ah=00h Al=33h Ax=0035h Ah=00h Al=35h Ax=0035h Ah=00h Al=35h Ax=0036h Ah=00h Al=36h

mov byte ptr [Msg1+edi],al

xchg ax,dx ;Ax=1999h:Dx=0035h; Ax=028Fh:Dx=0033h; Ax=0041h:Dx=0035h; Ax=0006h:Dx=0035h; Ax=0000h:Dx=0036h;

dec edi ; edi=4 edi=3 edi=2 edi=1 edi=0

or ax,ax ;1999 or 1999 = 1111h 028Fh or 028Fh=0111h 0041h or 0041h=0011h 0006h or 0006h=0001h 0000h or 0000h=0000h

; устанавливает флаг ZF в 1 если в АХ не 0

jne lp1

push 0h

push offset Ttl

push offset Msg

push 0h

call MessageBoxA

push 0h

call ExitProcess

end start

Таблица ASCII кодов.

0

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

0

...

...

0

@

P

'

Р

А

Р

а

...

...

...

р

Ё

1

...

...

!

1

A

Q

a

Q

Б

С

б

...

...

...

с

ё

2

...

...

"

2

B

R

b

R

В

Т

в

...

...

...

т

Є

3

...

...

#

3

C

S

c

S

Г

У

г

...

...

...

у

є

4

...

...

$

4

D

T

d

T

Д

Ф

д

...

...

...

ф

Ї

5

...

...

%

5

E

U

e

U

Е

Х

е

...

...

...

х

ї

6

...

...

&

6

F

V

f

V

Ж

Ц

ж

...

...

...

ц

Ў

7

...

...

'

7

G

W

g

W

З

Ч

з

...

...

...

ч

ў

8

...

...

(

8

H

X

h

X

И

Ш

и

...

...

...

ш

°

9

...

...

)

9

I

Y

i

Y

Й

Щ

й

...

...

...

щ

A

...

...

*

:

J

Z

j

Z

К

Ъ

к

...

...

...

ъ

·

B

...

...

+

;

K

[

k

{

Л

Ы

л

...

...

...

ы

C

...

...

,

<

L

\

l

|

М

Ь

м

...

...

...

ь

D

...

...

-

=

M

]

m

}

Н

Э

н

...

...

...

э

¤

E

...

...

.

>

N

^

n

~

О

Ю

о

...

...

...

ю

F

...

...

/

?

O

_

o

¤

П

Я

п

...

...

...

я

Блок-схема алгоритма вывода на экран содержимого регистра ах в любой системе исчисления:

1) Инициализация регистра данными: mov ax,C. Необходимо вывести на экран значение «С». С имеет размерность в 2 байта максимум.

2) Инициализация регистра si:

mov si,10 ;10-основание системы исчисления, в которую необходимо перевести значение С.

3) Инициализация регистра edi:

mov edi,5 ; 5 – количество позиций, которое отводится для десятичного числа (под ответ).

Обнуление регистра dx, в который будет записываться остаток от деления: xor dx,dx

1) Деление: С/10; dx-остаток, ax-целая часть.

2) Перевод остатка в ASCII символ: dx+30.

3) Запись символа ASCII в переменную Msg в позицию под номером edi.

С:=ах;

Edi:=edi-1;

Ax<>0

Нет

Да

Вывод значение переменной Msg с помощью функции MessageBoxA.

Решение задач.

Пример 2: 6*С+(В-С+1)/2

.386

.model flat, stdcall

extrn ExitProcess:PROC

.data

B DW 8

C DW 3

D Db 2

.code

start:

mov AX,6

mov BX,C

mul BX

mov Dx,AX

mov Ax,B

mov Bx,C

sub Ax,Bx

jl m1 ; отрицательный ли результат? Если да, то переход на метку m1. Если

;результат положительный, то продолжаем выполнять следующую команду.

add ax,1

xor bx,bx

mov bl,D

div bl

add ax,dx

jmp m2

m1: ; результат (B-C) оказывается отрицательным!

neg ax

mov bx,1

sub ax,bx

xor bx,bx

mov bl,D

div bl

neg ax

add Ax,Dx

m2:

push 0h

call ExitProcess

end start

Пример 1: 6*С+(В-С+1)/2

model small

.stack 100h

.data

B DW 8 ; резервирование памяти для данных размером 2 байт;

C DW 3 ; резервирование памяти для данных размером 2 байт;

D Db 2 ; резервирование памяти для данных размером 1 байт;

.code

start:

mov AX,@data

mov DS,AX

mov AX,6

mov BX,C

mul BX

mov Dx,AX

mov Ax,B

mov Bx,C

sub Ax,Bx

jl m1 ; отрицательный ли результат? Если да, то переход на метку m1. Если

;результат положительный, то продолжаем выполнять следующую команду.

add ax,1

xor bx,bx

mov bl,d

div bl

add ax,dx

jmp m2

m1: ; результат оказывается отрицательным!

neg ax

mov bx,1

sub ax,bx

xor bx,bx

mov bl,d

div bl

neg ax

add Ax,Dx

m2:

mov AX,4C00h

int 21h

end start