Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Устанавливает флаг cf в 1, фиксируя воображаемый заём из старшего разряда.

Поиск

Команда aas применяется вместе с основными командами вычитания sub и sbb.


В ассемблере отсутствует также формальное правило введения знака для неупакованных BCD- чисел. Решение этого вопроса остаётся за программистом. Как один из возможных можно принять принцип кодирования знака для упакованных чисел, который реализуется директивой DT. Например, число -386 (младший байт по старшему адресу) инициализируем следующим образом:

Oper DB 80h,6,8,3;Неупакованное BCD- число -386

 

Например: 2-7

.data

a db 02h

b db 07h

.code

xor ax,ax; очистка ах

xor bx,bx; очистка bx

mov al,a; в al занесли 1

sbb al,b; al=2-7; 0000 0010-0000 0111-0=1111 1011

aas; 1011-0110=0101, al=0000 0101, cf=1

 


Умножение

Для того, чтобы перемножить два одноразрядных BCD –числа необходимо:

1) поместить один из сомножителей в регистр al (этого требует команда mul);

2) поместить второй операнд в регистр или память, отведя байт;

3) перемножить сомножители командой mul (результат будет в ах);

4) результат получится в двоичном коде и его нужно корректировать.

Для коррекции результата после умножения применяется команда:

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

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

1) делит ax на 10;

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

 

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

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

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

 


Деление

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

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

Команда AAD:

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

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

Полученное двоичное число помещается в регистр 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 кодов.

                      A B C D E F
  ... ...     @ P ' Р А Р а ... ... ... р Ё
  ... ... !   A Q a Q Б С б ... ... ... с ё
  ... ... "   B R b R В Т в ... ... ... т Є
  ... ... #   C S c S Г У г ... ... ... у є
  ... ... $   D T d T Д Ф д ... ... ... ф Ї
  ... ... %   E U e U Е Х е ... ... ... х ї
  ... ... &   F V f V Ж Ц ж ... ... ... ц Ў
  ... ... '   G W g W З Ч з ... ... ... ч ў
  ... ... (   H X h X И Ш и ... ... ... ш °
  ... ... )   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
 
   
 
   
С:=ах; Edi:=edi-1;
 
   
 
   
 
   
Вывод значение переменной 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


Деление с остатком

Пример 2: Выполнить деление положительных чисел В/С; 1000/53=18,46/53. (real3.asm)

.386

.model flat, stdcall

includelib import32.lib

extrn ExitProcess:PROC

extrn MessageBoxA:PROC

.data

Ttl db "Rezultat deleniya raven",0h

Msg db 8 dup(' '),0h

db 0h

B DW 1000

C DW 53

 

.code

start:

mov ax,B

mov bx,C

mov dx,00h

div bx

 

cmp dx,0000h

jz m3; если остатка нет, то переходим на метку m3.

mov cx,ax

mov ax,C

mov bx,dx

mov si,10

mov edi,7

Если остаток есть, то переводим делитель в десятичную систему исчисления
lp2: xor dx,dx

div si

xchg ax,dx

add al,'0'

mov byte ptr [Msg+edi],al

xchg ax,dx

dec di

or ax,ax

jne lp2

mov byte ptr [Msg+edi],'/'

dec di

 

mov si,10

mov ax,bx

lp3: xor dx,dx

div si

xchg ax,dx

add al,'0'

mov byte ptr [Msg+edi],al

xchg ax,dx

dec di

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

jne lp3

 

mov byte ptr [Msg+edi],','

dec di

 

mov si,10

mov ax,cx

lp4: xor dx,dx

div si

xchg ax,dx

add al,'0'

mov byte ptr [Msg+edi],al

xchg ax,dx

dec di

or ax,ax

jne lp4

jmp m4

 

m3:

mov si,10

mov edi,7

lp5: xor dx,dx

div si

xchg ax,dx

add al,'0'

mov byte ptr [Msg+edi],al

xchg ax,dx

dec di

or ax,ax

jne lp5

 

m4:

push 0h

push offset Ttl

push offset Msg

push 0h

call MessageBoxA

push 0h

call ExitProcess

end start


Блок-схема вывода результата при делении с остатком

 


Числа с плавающей запятой. Работа с сопроцессором

В процессорах Intel все операции с плавающей запятой выполняет специальное устройство, FPU (Floating Point Unit), с собственными регистрами и собственным набором команд, поставлявшееся сначала в виде сопроцессора (8087, 80287, 80387, 80487), а начиная с 80486DX — встраивающееся в основной процессор.

Типы данных FPU



Поделиться:


Последнее изменение этой страницы: 2016-09-13; просмотров: 338; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.139.93.242 (0.008 с.)