Материал: 1117

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

; а не старшие разряды частного (правильно будет mov byte ptr result,al). Пример 2. Ошибочно используется регистр dx после деления слова на

слово:

 

xor dx,dx

;\

 

 

mov ax,w1

; |w1/w2

 

 

div w2 ;/

 

 

 

mov word ptr rezult,ax

 

 

mov word ptr result+2,dx; ошибка: в dx содержится остаток, а не

;

старшие разряды частного. Правильно будет mov word ptr result+2,0

 

Пример 3. Ошибочно используется регистр dx после деления двойно-

го слова на слово:

 

 

mov ax,word ptr d1

 

 

mov dx,word ptr d1+2

 

 

div w1

 

 

 

mov word ptr rezult,ax

; результат деления d1/w1

 

mov word ptr rezult+2,dx

;ошибка: в регистре dx содержится

 

;

 

остаток, а не старшие разряды частного

 

;

 

(правильно будет mov word ptr result+2,0)

Пример ошибочного использования регистра edx после деления учетверенного слова на двойное слово приведен в уч. пос., ч.7.

5.13. Потеря содержимого регистра при делении

Потеря содержимого регистра при делении заключается в том, что теряется значение, помещенное в регистр до операции деления (значение регистров al, ah, ax, dx теряется, т.к. туда заносится частное (в регистры al, ax) или остаток от деления (в регистры ah , dx).

Пример 1. Теряется содержимое ah после деления байта на байт:

mov ah,b3

; ah:=b3

mov al,b1

; b1/b2

div b2

 

mov byte ptr rezult,al

add al,ah ; ошибка: в регистре ah содержится остаток, а не b3 ; (правильно будет команду mov ah,b3 выполнять не до деления, а после).

Пример 2. Теряется содержимое dx после деления слова на слово:

mov dx,w3

 

mov ax,w1

; w1/w2

div w2

 

mov word ptr rezult,ax

mov word ptr result+2,0 ; ошибка: в регистре dx содержится

;остаток, а не w3 (правильно будет команду mov dx,w3

;

выполнять после деления, а не до него).

86

5.14. Неправильное использование регистров в командах cbw и cwd

Неправильное использование регистров при преобразовании байта в слово и слова в двойное слово заключается либо в ошибочном размещении исходного значения, либо в использовании в качестве результата не регистров ax (dx:ax). Для cbw и cwd исходные значения должны быть размещены в регистрах al и ax, соответственно. Программисты же иногда ошибочно помещают исходное значение в какой-нибудь другой регистр (например, в bl или bx).

Пример 1.

mov bl,b3

; bl := b3

cbw

; ошибка: результат, получившийся в ax, не имеет никакого

;

отношения к регистру bl (а значит, и к b3)

Пример 2.

 

mov al,b3

; al := b3

cbw

; результат получился в регистре ax

mov rez_w,bx ; ошибка: в bx не содержится результат выполнения

;команды cbw

5.15.Применение команд преобразования cbw и cwd

кбеззнаковым данным

При применении команд cbw и cwd к беззнаковым данным может возникнуть ошибка. Когда знаковый бит равен единице, старший байт или слово соответственно заполняется единицами, а не нулями, как это требуется в данном случае. Это надо учитывать при выполнении логических операций и операций сдвига и вместо инструкций cbw и cwd применять зануление старшего байта или слова командой xor. Например, если al= 128 (т.е. 100000002), то после выполнения команды cbw в регистре ax будет число 65408 (т.е. 11111111100000002), а должно остаться равным

128, но расширенным на 16 битов (т.е. 00000000100000002).

5.16.Изменение отдельными инструкциями флага переноса

Вто время как некоторые инструкции "непредвиденным" образом изменяют содержимое регистров или флагов, другие инструкции не влияют на все те флаги, изменения которых вы ожидаете. Например, инструкция

inc ah

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

add ah,1

и это действительно так, но инструкция add в случае слишком большого для операнда-приемника результата устанавливает флаг переноса, а инструкция inc на флаг cf не влияет. В результате инструкции

add ax,1

; ax := ax+1 (и cf:=1, если возник перенос)

 

87

adc dx,0 ; dx := dx+0+<значение cf>

можно использовать для увеличения 32-битового значения, хранящегося в регистрах dx: ax, а инструкции

inc ax ; ax:=ax+1 (cf не меняется, даже если возник перенос) adc dx,0

нельзя. То же самое имеет место для инструкции dec. Инструкции loop, loopz и loopnz также не влияют на состояние флагов (см. уч. пос., ч.6 и 7). Это можно использовать, например, в тех случаях, когда нужно организовать цикл и при этом не изменять значения флагов, в т.ч. и флага переноса.

5.17. Программист долго не использует состояние флагов

Состояние флагов сохраняется до тех пор, пока следующая инструкция их не изменит. Обычно это не слишком долгий интервал времени. Хорошей практикой программирования является возможно скорейшее использование флагов их установки, что позволяет избежать многих потенциальных ошибок. Например, часто хочется проверить условие, задать содержимое одного-двух регистров и только после этого в соответствии с результатом проверки выполнить переход. Инструкции:

cmp

ax,1

;вычисление (ax-1) без присвоения полученного значения

;

ах и присвоение значений (0 или 1 – зависит от результата) флагам:

;

нуля (zf), знака (sf), переноса (cf) и других (of , af и pf)

mov

ax,0

;ax:=0 значения флагов не изменяет

jg

 

Positive

; если больше (т.е если zf=0 и sf=of), переход на Positive

представляют собой допустимый способ проверки состояния регистра ax, установки его в значение 0 и обработки результата. А инструкции:

cmp

ax,1

sub

ax,ax ; присвоение значений (0 или 1 – зависит от результата)

;

флагам:нуля (zf), знака (sf), переноса (cf) и других (of , af и pf)

jg

Positive

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

5.18. Ошибки при использовании регистров

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

1.Нельзя задавать 8- и 16-разрядный (а для процессора 80386 также 8-

и32-разрядный или 16- и 32-разрядный) регистры для записи двух

88

операндов одной команды (это правило не распространяется на команды movsx и movzx, см. уч. пос., ч.7).

2.Операции со стеком должны осуществляться только в 16-битовых кодах. Если 8-разрядный регистр указывают для работы со стеком (push/pop), то выдается сообщение об ошибке.

3.Сегментные регистры не могут прямо использоваться в арифметических вычислениях, логических операциях или для непосредственной передачи данных. Кроме того, сегментные регистры могут быть использованы только либо как источники операндов, либо только как приемники операндов, но никак не одновременно.

Неверные записи

add ax,dl ; а) одновременное использование

;8-битового регистра (dl) и 16-битового регистра (ax) push bl ; б) 8-разрядный регистр указывают для работы со стеком

add ds,100 ; в) сегментный регистр ds используется при сложении

mov es,200 ; г) непосредственный операнд передается в регистр es

mov ss,cs

 

;д)оба операнда являются сегментными регистрами

Ниже приведена правильная запись предыдущих примеров

xor dh,dh

 

 

 

add ax,dx

; а)

 

 

 

 

 

 

 

xor bh,bh

 

 

 

push bx

; б)

 

 

 

 

 

 

addcx,100

; в)

 

 

 

 

 

 

movcx,200

; г)

moves,cx

 

 

 

 

 

; д)

movcx,cs

movss,cx

 

 

 

89

5.19. Выход из диапазона адресов [5, с.124-125]

Все команды условного перехода используют режим относительной адресации с 8-битовым смещением. Если относительный адрес символа, используемого в качестве операнда-адреса перехода, выходит за диапазон + 127 байтов -128 байтов от конца команды условного перехода, выдается сообщение об ошибке.

Неверные записи

and al,7fh

 

je next_proc

;между символическим адресом end_proc и next_proc

;

более 127 байтов (это важно, т .к. при выполнении

end_proc:

; команды je указатель команды (ip) показывает

;

на end_proc, а перейти надо на next_proc)

ret

data dw 300 dup(?) next_proc:

clc

Ниже приведена правильная запись предыдущего примера: and al,7fh

jne end_proc jmp next_proc

end_proc: ret

data dw 300 dup(?) next_proc:

clc

Библиографический список

1.Зубков С.В. Assembler для DOS, Windows и UNIX.–3-е изд., стер.–

М.: ДМК Пресс; СПб.: Питер, 2005.– 608 с.

2.Бурдаев О.В., Иванов М.А., Тетерин И.И. Ассемблер в задачах защиты информации/ Под ред. И.Ю.Жукова. – М.: КУДИЦ-ОБРАЗ, 2002. – 320 с.

3.Абель Питер. Ассемблер и программирование для IBM PC. Британская Колумбия. Технологический институт.

4.Олейник Л.Е. Язык ассемблера для микропроцессора 8086: Курс лекций. – Омск: Сибирская региональная школа бизнеса, 2000.

5.Дао. Л. Программирование микропроцессора 8088. – М.: Мир, 1988.

–356 с.

6.Абель Питер. Язык и программирование для IBM PC: Пер. с англ.– Киев: Век; М.: Энтроп; Киев: НТИ, 2003. – 736 с.

90

Источник: https://studfile.net/preview/16407174/