Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Dos7book

.pdf
Скачиваний:
76
Добавлен:
09.02.2015
Размер:
5.1 Mб
Скачать

Глава 7: Ассемблерные команды отладчика Debug.exe

Примечание 3: когда команда JMP получает адрес перехода по ссылке, характер операции зависит от наличия в строке вызова маркера "FAR". Когда он имеется, из памяти считывается полный четырехбайтовый адрес, и выполняется дальний переход. А при отсутствии маркера "FAR" из памяти считывается двухбайтовое слово. Оно интерпретируется как смещение, и тогда выполняется ближний переход.

Примечание 4: если команда JMP получает адрес перехода из регистра, то в этот регистр заранее должно быть записано смещение. Обращение JMP к 16-битовому регистру всегда вызывает ближний переход.

Примечание 5: после каждого переключения процессора из реального режима в защищенный и обратно, как правило, сразу же выполняют дальний переход (JMP FAR) на адрес следующей команды в том же сегменте кода. Эта команда JMP FAR нужна не для осуществления перехода, а ради двух других действий: во-первых, она приводит статус числа в регистре CS: (сегментный адрес или селектор) в соответствие с устанавливаемым режимом, и, во-вторых, она сбрасывает очередь команд, которую процессоры формируют на основании опережающей выборки, чтобы не оставлять там команды, дешифрированные по правилам прежнего режима.

Примечание 6: отладчик DEBUG.EXE дизассемблирует коды "FF E(8-F)" как команду "JMP FAR bx".

7.03-40 JNB – переход, если больше или равно

Команда JNB (Jump if Not Below) суммирует байт данных с содержимым регистра IP, если флаг CF сброшен в состояние NC (No Carry). В результате происходит "короткий" переход к исполнению машинной команды, находящейся в пределах ±7Fh от прежнего значения смещения в регистре IP.

Команда JNB используется для исполнения переходов по условию успешного завершения прерываний, которые отмечают успех сбросом флага CF в состояние NC, а также по результатам операций над числами без знака, в частности, после команд CMP, SBB, SUB (для чисел со знаком условие "больше или равно" проверяет команда JGE, 7.03-36).

Отладчик DEBUG.EXE принимает команду JNB также под именем JNC (Jump if Not Carry), но тем не менее дизассемблирует код 73h всегда как команду JNB.

1-й байт

2-й байт

Байты данных

Пример

73

 

1

JNB aaaa

– 279 –

Глава 7: Ассемблерные команды отладчика Debug.exe

7.03-41 JNO – переход, если нет переполнения

Команда JNO (Jump if No Overflow) суммирует байт данных с содержимым регистра IP, если флаг OF сброшен в состояние NV (No oVerflow). В результате происходит "короткий" переход к исполнению машинной команды, расположенной в пределах ±7Fh от прежнего значения смещения в регистре IP.

1-й байт

2-й байт

Байты данных

Пример

71

 

1

JNO aaaa

7.03-42 JNS – переход по положительному знаку числа

Команда JNS (Jump if not Sign) суммирует байт данных с содержимым регистра IP, если флаг SF сброшен в состояние PL, что соответствует положительному знаку числа. В результате происходит "короткий" переход к исполнению машинной команды, расположенной в пределах ±7Fh от прежнего значения смещения в регистре IP.

1-й байт

2-й байт

Байты данных

Пример

79

 

1

JNS aaaa

7.03-43 JNZ – переход по ненулевому результату или по условию неравенства

Команда JNZ (Jump if Not Zero) суммирует байт данных с содержимым регистра IP, если флаг ZF сброшен в состояние NZ (No Zero). В результате происходит "короткий" переход к исполнению машинной команды, расположенной в пределах ±7Fh от прежнего значения смещения в регистре IP.

Отладчик DEBUG.EXE принимает команду JNZ также под именем JNE (Jump if Not Equal), но тем не менее дизассемблирует код 75h всегда как команду JNZ .

1-й байт

2-й байт

Байты данных

Пример

75

 

1

JNZ aaaa

7.03-44 JO – переход при переполнении

Команда JO (Jump if Overflow) суммирует байт данных с содержимым регистра IP, если флаг OF установлен в состояние OV (OVerflow). В результате происходит "короткий" переход к исполнению машинной команды, расположенной в пределах ±7Fh от прежнего значения смещения в регистре IP.

– 280 –

Глава 7: Ассемблерные команды отладчика Debug.exe

 

1-й байт

2-й байт

Байты данных

Пример

 

70

 

 

1

JO aaaa

7.03-45

JPE – переход по четному результату

 

Команда JPE (Jump if Parity Even) суммирует байт данных с содержимым регистра IP, если флаг четности PF установлен в состояние PE, что соответствует

четной сумме битов в младшем байте результата предшествовавшей операции (остальные байты не учитываются). При этом условии происходит "короткий" переход к исполнению машинной команды, расположенной в пределах ±7Fh от прежнего значения смещения в регистре IP.

Отладчик DEBUG.EXE принимает команду JPE также под именем JP (Jump if Parity), но тем не менее дизассемблирует код 7Ah всегда как команду JPE.

1-й байт

2-й байт

Байты данных

Пример

7A

 

1

JPE aaaa

7.03-46 JPO – переход по нечетному результату

Команда JPO (Jump if Parity Odd) суммирует байт данных с содержимым регистра IP, если флаг четности PF сброшен в состояние PO, что соответствует

нечетной сумме битов в младшем байте результата предшествовавшей операции (остальные байты не учитываются). При этом условии происходит "короткий" переход к исполнению машинной команды, расположенной в пределах ±7Fh от прежнего значения смещения в регистре IP.

Отладчик DEBUG.EXE принимает команду JPO также под именем JNP (Jump if Not Parity), но тем не менее дизассемблирует код 7Bh всегда как команду JPO.

1-й байт

2-й байт

Байты данных

Пример

7B

 

1

JPO aaaa

7.03-47 JS – переход по отрицательному знаку числа

Команда JS (Jump if Sign) суммирует байт данных с содержимым регистра IP, если флаг SF установлен в состояние NG, что соответствует отрицательному знаку числа. В результате происходит "короткий" переход к исполнению машинной команды, расположенной в пределах ±7Fh от прежнего значения смещения в регистре IP.

– 281 –

Глава 7: Ассемблерные команды отладчика Debug.exe

1-й байт

2-й байт

Байты данных

Пример

78

 

1

JS aaaa

7.03-48 JZ – переход по нулевому результату или по условию равенства

Команда JZ (Jump if Zero) суммирует байт данных с содержимым регистра IP, если флаг ZF установлен в состояние ZR (ZeRo). В результате происходит "короткий" переход к исполнению машинной команды, расположенной в пределах ±7Fh от прежнего значения смещения в регистре IP.

Отладчик DEBUG.EXE принимает команду JZ также под именем JE (Jump if Equal), но тем не менее дизассемблирует код 74h всегда как команду JZ .

1-й байт

2-й байт

Байты данных

Пример

74

 

1

JZ aaaa

7.03-49 LAHF – копирование флагов в регистр

Команда LAHF (Load AH with Flags) копирует младший байт из регистра флагов в однобайтовый регистр AH, так что состояние знакового флага SF отображается битом 7 в AH, состояние флага нуля ZF отображается битом 6, состояние дополнительного флага переноса AF отображается битом 4, состояние флага четности PF отображается битом 2, и состояние флага переноса CF отображается битом 0. Биты 5, 3 и 1 однобайтового регистра AH каким-либо флагам не соответствуют. Бит 1 всегда устанавливается в состояние логической единицы, биты 5 и 3 сбрасываются в нуль.

 

 

Код

Пример

 

 

9F

LAHF

7.03-50

LDS – загрузка регистра DS

 

Команда LDS (Load address into DS) выполняет загрузку полного адреса из памяти, причем сегментный адрес загружается в регистр DS, а смещение в другой регистр, указываемый в качестве первого операнда. Второй операнд команды LDS задает смещение, указывающее на ячейку памяти, откуда должен быть считан первый байт загружаемого полного адреса. Байты 2 и 1 полного адреса определяют смещение, байты 4 и 3 – сегментный адрес. Состояния флагов команда LDS не изменяет.

– 282 –

Глава 7: Ассемблерные команды отладчика Debug.exe

1-й байт

2-й байт

Байты данных

Пример

C5

(1,5,9)(8-F)

0-2

LDS bx,[bp+si+ffff]

Примечание 1: отладчик DEBUG.EXE ошибочно дизассемблирует как команду

LDS коды "C5 (C-F)(0-F)".

Примечание 2 по умолчанию пара регистров DS:SI считается определяющей адрес источника данных, и потому в качестве первого операнда команды LDS (вместо bx) наиболее часто указывают регистр SI.

Примечание 3: и сегментный адрес в регистре DS:, и смещение могут быть использованы для адресации и перезагружены в одной операции; например, вполне допустима команда DS: LDS SI,[SI].

7.03-51 LEA – вычисление смещения

Команда LEA (Load Effective Address) вычисляет выражение в квадратных скобках, которое задано в качестве второго операнда и определяет некоторое смещение. Результат вычисления загружается в регистр, указанный в качестве первого операнда. Состояния флагов команда LEA не изменяет.

1й байт

2-й байт

Байты данных

Пример

8D

(0-B)(0-F)

0-2

LEA bx,[bp+si+ffff]

7.03-52 LES – загрузка регистра ES

Команда LES (Load address into ES) выполняет загрузку полного адреса из памяти, причем сегментный адрес загружается в регистр ES, а смещение в другой регистр, указываемый в качестве первого операнда. Второй операнд команды LES задает смещение, указывающее на ячейку памяти, откуда должен быть считан первый байт загружаемого полного адреса. Байты 2 и 1 полного адреса определяют смещение, байты 4 и 3 – сегментный адрес. Состояния флагов команда LES не изменяет.

 

1-й байт

2-й байт

Байты данных

 

Пример

 

 

C4

(1,5,9)(8-F)

0-2

 

LES bx,[bp+si+ffff]

 

Примечание 1: отладчик DEBUG.EXE ошибочно

дизассемблирует как команду

LES коды "C4 (C-F)(0-F)".

Примечание 2: по умолчанию пара регистров ES:DI считается определяющей адрес назначения, и потому в качестве первого операнда команды LES (вместо bx) наиболее часто указывают регистр DI.

– 283 –

Глава 7: Ассемблерные команды отладчика Debug.exe

Примечание 3: и сегментный адрес в регистре ES:, и смещение могут быть использованы для адресации и перезагружены в одной операции; например, вполне допустима команда ES: LES DI,[DI].

7.03-53 LODSB – считывание байта

Команда LODSB (LOaD String of Bytes) считывает из памяти в однобайтовый регистр AL один байт, на который указывает полный адрес, заранее записанный в пару регистров DS:SI. После считывания смещение в регистре SI увеличивается или уменьшается на единицу: это зависит от состояния флага направления DF, которое следует заранее задать командой CLD (счет вверх, 7.03-11) или командой STD (счет вниз, 7.03-85). Состояния флагов команда LODSB не изменяет.

Команде LODSB может предшествовать префикс смены сегмента (7.02-01); он

позволит адресовать считываемый байт через другой сегментный регистр вместо принимаемого по умолчанию сегментного регистра DS.

 

Код

Пример

 

AC

LODSB

7.03-54 LODSW – считывание слова

 

Команда LODSW (LOaD String of Words) считывает в регистр AX одно двухбайтовое слово и изменяет смещение в регистре SI на 2, подготавливая тем самым адрес для считывания следующего слова. Под действием префикса 66h смены разрядности операнда (7.02-06) команда LODSW считывает в регистр EAX 4-байтовое слово (типа Dword) и изменяет смещение в регистре SI на 4. Остальные особенности команды LODSW такие же, как у команды LODSB (7.03-53).

 

Код

Пример

 

AD

LODSW

7.03-55 LOOP – организация цикла

 

Команда LOOP сначала уменьшает число в регистре CX на единицу, а потом проверяет, не равен ли остаток нулю. Пока он не равен нулю, будет выполняться "короткий" переход в пределах ±7Fh путем прибавления байта данных к смещению в регистре IP. А когда станет CX = 0, процессор перейдет к исполнению следующей команды. Состояния флагов команда LOOP не изменяет.

– 284 –

Глава 7: Ассемблерные команды отладчика Debug.exe

Счет циклов в регистре CX исходит из предположения, что команда LOOP следует за телом цикла. В этом случае тело цикла будет исполнено один раз, прежде чем условие вхождения в цикл будет проверено командой LOOP. Чтобы предотвратить исполнение тела цикла до проверки, можно перед телом цикла поставить команду JCXZ (7.03-34). Другое решение состоит в вынесении тела цикла из основной последовательности команд. В последнем случае число, заранее записываемое в регистр CX, должно быть на единицу больше требуемого числа актов исполнения цикла.

1-й байт

2-й байт

Байты данных

Пример

E2

 

1

LOOP aaaa

7.03-56 LOOPNZ – возврат в цикл, если не нуль

Команда LOOPNZ (LOOP if Not Zero) сначала уменьшает число в регистре CX на единицу, а затем проверяет два условия: отличается ли остаток в регистре CX от нуля и сброшен ли флаг нуля ZF в состояние NZ. Когда оба условия выполнены, происходит "короткий" переход в пределах ±7Fh путем прибавления байта данных к смещению в регистре IP. Если же хотя бы одно условие не удовлетворяется, то процессор просто переходит к исполнению следующей команды. Особенности организации циклов командой LOOPNZ такие же, как у команды LOOP (7.03-55). Состояния флагов команда LOOPNZ не изменяет.

Отладчик DEBUG.EXE принимает команду LOOPNZ также под именем LOOPNE (LOOP, if Not Equal = цикл, если не равно), но тем не менее дизассемблирует код E0h всегда как команду LOOPNZ.

1-й байт

2-й байт

Байты данных

Пример

E0

 

1

LOOPNZ aaaa

7.03-57 LOOPZ – возврат в цикл, если нуль

Команда LOOPZ (LOOP if Zero) сначала уменьшает число в регистре CX на единицу, а затем проверяет два условия: отличается ли остаток в регистре CX от нуля и установлен ли флаг нуля ZF в состояние ZR. Когда оба условия выполнены, происходит "короткий" переход в пределах ±7Fh путем прибавления байта данных к смещению в регистре IP. Если же хотя бы одно условие не удовлетворяется, то процессор просто перейдет к исполнению следующей команды. Особенности организации циклов командой LOOPZ такие же, как у команды LOOP (7.03-55). Состояния флагов команда LOOPZ не изменяет.

– 285 –

Глава 7: Ассемблерные команды отладчика Debug.exe

Отладчик DEBUG.EXE принимает команду LOOPZ также под именем LOOPE (LOOP, if Equal = цикл, если равно), но тем не менее дизассемблирует код E1h всегда как команду LOOPZ.

 

1-й байт

2-й байт

Байты данных

Пример

 

E1

 

 

1

LOOPZ aaaa

7.03-58

MOV – копирование данных

 

Команда MOV копирует байт или слово данных, определяемых прямо или косвенно вторым операндом, в регистр или в ячейку памяти, задаваемые первым операндом. Явное указание размера копируемых данных байт или слово требуется только когда в качестве операнда не указан регистр процессора. Обычные формы команды MOV состояния флагов не изменяют; исключение составляют только обращения к управляющим, отладочным и тестовым регистрам, показанные ниже в примечании 1 (после них состояния флагов OF, SF, ZF, AF, PF, CF могут не сохраняться).

1-й байт

2-й байт

Байты

Примеры

данных

 

 

 

88

(0-B)(0-5, 7-F)

0-2

MOV [bp+si+ffff],bl

88

(C-F)(0-F)

 

MOV bl,bl

89

(0-B)(0-5, 7-F)

0-2

MOV [bp+si+ffff],bx

89

(C-F)(0-F)

 

MOV bx,bx

8A

(0-B)(0-5, 7-F)

0-2

MOV bl,[bp+si+ffff]

8B

(0-B)(0-5, 7-F)

0-2

MOV bx,[bp+si+ffff]

8C

(0,1,4,5,8,9)(0-F)

0-2

MOV [bp+si+ffff],ss

8C

(C,D,E)(0-F)

 

MOV bx,ss

8E

(0,1,4,5,8,9)(0-F)

0-2

MOV ss,[bp+si+ffff]

8E

(C,D,E)(0-F)

 

MOV ss,bx

A0

 

2

MOV AL,[ffff]

A1

 

2

MOV AX,[ffff]

A2

 

2

MOV [ffff],AL

A3

 

2

MOV [ffff],AX

B(0-7)

 

1

MOV bl,ff

B(8-F)

 

2

MOV bx,ffff

C6

(0,4,8)(0-7)

1-3

MOV byte ptr [bp+si+ffff],ff

C7

(0,4,8)(0-7)

2-4

MOV word ptr [bp+si+ffff],ffff

Примечание 1: отладчик DEBUG.EXE "не знает" команд обращения к управляющим и отладочным регистрам 32-разрядных процессоров,

но коды этих команд можно вводить как данные с помощью

– 286 –

Глава 7: Ассемблерные команды отладчика Debug.exe

инструкции DB (7.01-01). Такие команды копирования трехбайтовые, начинаются с байта 0Fh; второй байт определяет исполнение копирования:

20h – из управляющего регистра (CR0, CR2 – CR4) 21h – из отладочного регистра (DR0 – DR3, DR6, DR7) 22h – в управляющий регистр (CR0, CR2 – CR4)

23h – в отладочный регистр (DR0 – DR3, DR6, DR7)

Третий байт в таких командах указывает на конкретные регистры: C0h – на CR0 или DR0, например, 0F 20 C0 = MOV EAX,CR0 C8h – на DR1, например, 0F 23 C8 = MOV DR1,EAX D0h – на CR2 или DR2, например, 0F 20 D0 = MOV EAX,CR2 D8h – на CR3 или DR3, например, 0F 20 D8 = MOV EAX,CR3

E0h – на CR4,

например, 0F 22 E0 = MOV CR4,EAX

F0h – на DR6,

например, 0F 21 F0 = MOV EAX,DR6

F8h – на DR7,

например, 0F 23 F8 = MOV DR7,EAX

Чтобы вместо EAX задействовать какой-либо иной регистр, нужно к 3-му байту прибавить номер этого регистра (от 00h до 07h) в

следующем перечне: EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,

например:

0F 20 C3 = MOV EBX,CR0

Отладчик DEBUG.EXE неспособен дизассемблировать эти коды, но не препятствует отладке программ, которые такие коды содержат, при условии работы на компьютере с 32-разрядным процессором.

Префикс смены разрядности операнда перед такими командами не требуется.

Примечание 2: отладчик DEBUG.EXE "не знает" команд обращения к сегментным регистрам GS: и FS:, имеющимся в 32-разрядных процессорах, но

коды этих команд можно вводить как данные с помощью инструкции DB (7.01-01). Такие команды копирования двухбайтовые:

8C E0 = MOV AX,FS

8C E8 = MOV AX,GS

8E E0 = MOV FS,AX

8E E8 = MOV GS,AX

Чтобы вместо AX задействовать какой-либо иной регистр, нужно ко 2-му байту прибавить номер этого регистра (от 00h до 07h) в перечне, приведенном во 2-й строке таблицы 7.00, например:

8E E3 = MOV FS,BX

Отладчик DEBUG.EXE ошибочно дизассемблирует такие коды как относящиеся к регистрам CS: и ES:, но не препятствует правильной отладке программ, которые такие коды содержат, при условии работы на компьютере с 32-разрядным процессором.

– 287 –

Глава 7: Ассемблерные команды отладчика Debug.exe

Примечание 3: команду MOV нельзя использовать для записи данных в регистр CS:, это можно делать только посредством команд перехода или команд передачи управления (CALL, JMP, RETF и т.п.).

Примечание 4: команда копирования слова данных в регистр SS вызывает

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

Примечание 5: отладчик DEBUG.EXE дизассемблирует как команду MOV коды

"8(A,B) (C-F)(0-F)", "8(C,E) (2,3,6,7,A,B,F)(0-F)" и "C(6,7) (C-F)(0-F)".

7.03-59 MOVSB – копирование байта

Команда MOVSB (MOVe a String of Bytes) копирует один байт из адреса источника в адрес назначения. Оба адреса должны быть подготовлены заранее: адрес источника в паре регистров DS:SI, адрес назначения в паре регистров ES:DI. После копирования оба смещения смещение источника в регистре SI и смещение назначения в регистре DI – увеличиваются на единицу или уменьшаются на единицу: это зависит от состояния флага направления DF, которое следует заранее задать командой CLD (счет вверх, 7.03-11) или командой STD (счет вниз, 7.03-85). Автоматическое изменение смещений в индексных регистрах

подготавливает условия для копирования следующего байта в следующую ячейку памяти. Состояния флагов команда MOVSB не изменяет.

Перед командой MOVSB часто ставится префикс повторения REPNZ (7.02-03) или REPZ (7.02-04), что позволяет исполнять команду MOVSB несколько раз и таким образом копировать сразу строку байтов. Также перед командой MOVSB можно ставить один из префиксов смены сегмента (7.02-01); это позволяет

отсчитывать адрес источника относительно другого сегментного регистра вместо принимаемого по умолчанию сегментного регистра DS:. Сегментный регистр адреса назначения (ES:) посредством префикса смены сегмента изменить нельзя.

 

Код

 

Пример

 

A4

 

MOVSB

7.03-60 MOVSW – копирование слова

 

Команда MOVSW (MOVe a String of Words) копирует двухбайтовое слово и затем изменяет смещение в адресах источника и назначения на 2, подготавливая их

– 288 –

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