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

Dos7book

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

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

исполняется центральным процессором только тогда, когда сброшен бит 02h ("эмуляция сопроцессора") в управляющем регистре CR0 (A.11-4). Если же бит 02h установлен, то в ответ на поступление каждой такой команды центральный процессор генерирует прерывание INT 07 (8.01-08), позволяющее осуществить программную эмуляцию функций сопроцессора или других устройств.

Команда ESC потенциально может быть применена для передачи данных и команд к асинхронно работающим устройствам, однако для современных процессоров такая возможность не документирована. Первый операнд команды ESC – шестнадцатеричный номер, второй операнд считывается из указанного регистра. Интерпретация операндов определяется адресуемым устройством. Состояния флагов команда ESC не изменяет.

1-й байт

2-й байт

Примеры

DA

C(0-7)

ESC 10,bl

DA

C(8-F)

ESC 11,bl

DA

D(0-7)

ESC 12,bl

DA

D(8-F)

ESC 13,bl

DA

E(0-7)

ESC 14,bl

DA

E(8-F)

ESC 15,bl

DA

F(0-7)

ESC 16,bl

DA

F(8-F)

ESC 17,bl

7.03-23 HLT – останов процессора

Команда HLT вызывает останов процессора, при котором сохраняются адреса в регистрах CS:IP и флаги, обеспечивающие возможность правильной активизации процессора. Вывести процессор из состояния останова можно посредством перезагрузки или по сигналу внешнего прерывания, поступившему либо на вход NMI (8.01-03), либо через контроллер прерываний (8.01-09).

Код

Пример

F4

HLT

Примечание 1: команда HLT исполняется только в программах с высшим (нулевым) уровнем привилегий.

Примечание 2: когда небезразлично, каким именно внешним прерыванием процессор выведен из состояния останова, тогда выяснить номер прерывания можно так, как описано в разделе 8.01-09.

– 269 –

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

7.03-24 IDIV – деление чисел со знаком

Команда IDIV (Integer DIVide) осуществляет деление целых чисел со знаком (для чисел без знака используют команду DIV, 7.03-21). Задаваемый в команде IDIV операнд это делитель. Если делитель представляет собой байт, то заранее предполагается наличие делимого в регистре AX; после деления частное помещается в AL, а остаток в AH. Если делитель представляет собой двухбайтовое слово, то заранее предполагается наличие старших разрядов делимого в регистре DX, младших разрядов делимого в регистре AX; после деления частное помещается в регистр AX, а остаток в регистр DX. Знак остатка в регистре DX всегда совпадает со знаком делимого. Состояния флагов OF, SF, ZF, AF, PF, CF не сохраняются, после деления они остаются в неопределенном состоянии.

Хотя команда IDIV является двоичной операцией, тем не менее неупакованные

десятичные двухбайтовые слова могут быть подвергнуты операции двоичного деления, если они заранее преобразованы в приемлемую квази-двоичную форму командой AAD (7.03-02).

1-й байт

2-й байт

Байты

Примеры

данных

 

 

 

F6

(3,7,B)(8-F)

0-2

IDIV byte ptr [bp+si+ffff]

F6

F(8-F)

 

IDIV bl

F7

(3,7,B)(8-F)

0-2

IDIV word ptr [bp+si+ffff]

F7

F(8-F)

 

IDIV bx

Примечание 1: если операция деления вызывает переполнение в том регистре, куда должно быть помещено частное, то процессор автоматически вызывает обработчика прерывания INT 00 (8.01-01). Дальнейший ход событий зависит от этого обработчика.

7.03-25 IMUL – умножение чисел со знаком

Команда IMUL (Integer MULtiplcation) осуществляет умножение целых чисел со знаком (для чисел без знака используют команду MUL, 7.03-61). Операнд команды IMUL представляет одного из сомножителей. Если этот операнд байт, то второй сомножитель должен быть заранее помещен в регистр AL, а результат умножения будет оставлен в регистре AX. Если задаваемый в команде операнд является двухбайтовым словом, то второй сомножитель должен быть заранее помещен в регистр AX, старшие два байта произведения будут оставлены в регистре DX, а младшие два байта в регистре AX.

– 270 –

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

При исполнении умножения установление флагов OF и CF в состояния OV и CY свидетельствует о том, что старшая часть произведения в регистре AH или в регистре DX содержит значимые цифры. Напротив, сброс флагов OF и CF в состояния NV и NC означает, что старшая часть произведения заполнена только знаковым разрядом. Состояния флагов SF, ZF, AF и PF не сохраняются, они остаются в неопределенном состоянии.

Умножать командой IMUL можно двоичные и неупакованные десятичные числа. Упакованные десятичные числа необходимо сначала распаковать. В

результате умножения неупакованных десятичных чисел получается двоичное произведение, которое следует преобразовать в правильное неупакованное десятичное число командой AAM (7.03-03).

1-й байт

2-й байт

Байты

Примеры

данных

 

 

 

F6

(2,6,A)(8-F)

0-2

IMUL byte ptr [bp+si+ffff]

F6

E(8-F)

 

IMUL bl

F7

(2,6,A)(8-F)

0-2

IMUL word ptr [bp+si+ffff]

F7

E(8-F)

 

IMUL bx

Примечание 1: варианты команды IMUL с указанием двух и трех операндов (коды 69h и 6Bh) не поддерживаются отладчиком DEBUG.EXE.

7.03-26 IN – ввод данных из порта

Команда IN считывает данные из порта. В течение времени ее исполнения процессор выдает сигнал, по которому происходит переключение шин процессора с памяти на устройства ввода-вывода, и обеспечивается асинхронный прием данных. Первый операнд команды IN задает регистр для размещения считанных данных в соответствии с их форматом: регистр AL, если должен быть считан байт, или регистр AX, если должно быть считано двухбайтовое слово. Номер порта определяется вторым операндом, либо находящимся в регистре DX, либо указываемым в команде двухзначным шестнадцатеричным числом. На состояния флагов команда IN не влияет.

1-й байт

2-й байт

Байты данных

Примеры

E4

 

1

IN AL,ff

E5

 

1

IN AX,ff

EC

 

 

IN

AL,DX

ED

 

 

IN

AX,DX

– 271 –

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

Примечание 1: номера

некоторых портов

приведены в

приложении A.14-1.

Запросы к портам с номерами свыше FFh выполняются только через

регистр DX.

 

 

Примечание 2: команда

IN не выполняется

из программ,

уровень привилегий

которых ниже уровня, установленного для операций ввода-вывода в битах 0Ch и 0Dh регистра флагов (A.11-4).

7.03-27 INC – увеличение на единицу

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

1-й байт

2-й байт

Байты

Примеры

данных

 

 

 

4(0-7)

 

 

INC bx

FE

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

0-2

INC byte ptr [bp+si+ffff]

FE

C(0-7)

 

INC bl

FF

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

0-2

INC word ptr [bp+si+ffff]

Примечание 1: байты 4(0-F) интерпретируются 64-разрядными процессорами как префиксы (7.02-08). Поэтому вместо однобайтового кода 4(0-7) команды "INC bx" предпочтительно применять двухбайтовый код "FF C(0-7)". Он воспринимается как команда "INC bx" всеми процессорами платформы x86 и правильно дизассемблируется отладчиком DEBUG.EXE, но при ассемблировании его приходится вводить как данные инструкцией DB (7.01-01).

7.03-28 INT – вызов обработчика прерывания

Команда INT (INTerrupt) передает управление обработчику того прерывания, номер которого определен ее операндом, предварительно обеспечив возможность возврата к исполнению текущей программы. Для этого команда INT выполняет следующую последовательность действий:

сохраняет в стеке состояние регистра флагов;

сохраняет в стеке состояние регистра CS;

рассчитывает и сохраняет в стеке адрес (смещение) следующей команды для восстановления состояния регистра IP;

сбрасывает флаг IF в состояние DI, перекрывая тем самым поступление запросов через контроллер прерываний;

сбрасывает очередь команд, которую процессоры формируют на основании опережающей выборки;

272 –

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

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

считывает адрес обработчика и передает ему управление путем записи его адреса (сегмента и смещения) в регистры CS:IP.

Состав и порядок расположения сохраняемых в стеке данных обеспечивают возврат к текущей программе посредством команды IRET (7.03-30), которая должна быть последней в коде любого обработчика прерывания. После возврата исполнение программы продолжится с команды, следующей за командой INT.

Почти каждому обработчику прерывания для исполнения его миссии должны быть предоставлены определенные условия и исходные данные. Об этом нужно побеспокоиться заранее, до вызова прерывания командой INT. Сведения о

функциях и условиях вызова некоторых важных обработчиков прерываний приведены в главе 8.

1-й байт

2-й байт

Байты данных

Примеры

CC

 

 

INT

3

CD

 

1

INT

ff

Примечание 1: исходное состояние флага прерывания IF на исполнение команды INT не влияет. Флаг IF влияет только на исполнение внешних запросов, поступающих через контроллер прерываний.

Примечание 2: команда INT 3 (CCh), в отличие от всех остальных программных прерываний, не зависима от уровня привилегий, то есть при любом режиме процессора исполняется так же, как в реальном режиме.

Примечание 3: смещение следующей команды записывается в стек только при исполнении команд INT или INTO. Все остальные не-внешние прерывания записывают в стек текущее состояние регистра IP.

Примечание 4: чтобы обработчик прерывания смог пользоваться данными, сохраняемыми в стеке командой INT, нужно сразу после передачи управления зафиксировать состояние указателя стека (SP) в регистре BP, и тогда адрес [BP+00] укажет на смещение команды, которая будет исполнена после возврата в программу, вызвавшую прерывание. Сегментный адрес этой программы будет в ячейке [BP+02], а состояние флагов в ячейке [BP+04].

7.03-29 INTO – прерывание при переполнении

Немедленная реакция на переполнение посредством вызова прерывания INT 00 (8.01-01) применима не всегда. Для обеспечения возможности более гибкой и отложенной обработки подобных ошибок введена команда INTO (= INTerrupt if Overflow). Она проверяет флаг переполнения OF, и если этот флаг установлен в

– 273 –

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

состояние OV (OVerflow), то вызывает на исполнение обработчик прерывания INT 04 (8.01-05) так же, как выполняет прерывания команда INT (7.03-28).

Код

Пример

CE

INTO

Примечание 1: загружаемый по умолчанию обработчик прерывания INT 04 просто возвращает управление в вызвавшую его программу. Если нужна какая-либо иная реакция на переполнение, то следует заранее побеспокоиться о том, чтобы подготовить другой обработчик и вписать его адрес в таблицу прерываний (8.02-18).

7.03-30 IRET – возврат из обработчика прерывания

Команда IRET (Interrupt RETurn) восстанавливает по сохраненным в стеке данным прежние состояния регистров IP, CS и флагов, чем обеспечивается возврат к продолжению исполнения программы, вызвавшей прерывание. Исполнение кода любого обработчика прерывания должно кончаться командой IRET.

Код

Пример

CF

IRET

Примечание 1: установление состояния регистра флагов командой IRET не подвержено тем ограничениям, которые наложены на команду POPF (7.03-68), и дает шанс их обойти.

Примечание 2: команда IRET сбрасывает очередь команд, которую процессоры формируют на основании опережающей выборки, чтобы после возврата следующие команды были дешифрированы по правилам, установленным для вызывающей программы.

7.03-31 JA – переход, если больше

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

Команда JA используется после выполнения операций над числами без знака, в частности, после команд CMP, SBB, SUB (для чисел со знаком условие "больше" проверяет команда JG, 7.03-35).

– 274 –

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

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

1-й байт

2-й байт

Байты данных

Пример

77

 

1

JA aaaa

7.03-32 JB – переход, если меньше

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

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

Отладчик DEBUG.EXE принимает команду JB также под именами JNAE (Jump if Not Above or Equal) и JC (Jump if Carry), но тем не менее дизассемблирует код 72h

всегда как команду JB.

1-й байт

2-й байт

Байты данных

Пример

72

 

1

JB aaaa

7.03-33 JBE – переход, если меньше или равно

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

Команда JBE используется после выполнения операций над числами без знака, в частности, после команд CMP, SBB, SUB (для чисел со знаком условие "меньше или равно" проверяет команда JLE, 7.03-38)..

Отладчик DEBUG.EXE принимает команду JBE также под именем JNA (Jump if Not Above), но тем не менее дизассемблирует код 76h всегда как команду JBE.

– 275 –

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

1-й байт

2-й байт

Байты данных

Пример

76

 

1

JBE aaaa

7.03-34 JCXZ – переход по нулю в регистре CX

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

Поскольку регистр CX обычно играет роль счетчика циклов, постольку команда JCXZ позволяет заранее проверить условие исполнения цикла и обойти его, когда число в регистре CX оказывается равным нулю до входа в цикл.

1-й байт

2-й байт

Байты данных

Пример

E3

 

1

JCXZ aaaa

7.03-35 JG – переход, если больше

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

Команда JG используется после выполнения операций над числами со знаком, в частности, после команд CMP, SBB, SUB (для чисел без знака условие "больше" проверяет команда JA, 7.03-31).

Отладчик DEBUG.EXE принимает команду JG также под именем JNLE (Jump if Not Lower or Equal), но дизассемблирует код 7Fh всегда как команду JG.

1-й байт

2-й байт

Байты данных

Пример

7F

 

1

JG aaaa

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

Команда JGE (Jump if Greater or Equal) суммирует байт данных с содержимым регистра IP, если флаг знака SF и флаг переполнения OF находятся в одном состоянии, то есть оба установлены или оба сброшены. В результате

– 276 –

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

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

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

Отладчик DEBUG.EXE принимает команду JGE также под именем JNL (Jump if Not Lower), но тем не менее дизассемблирует код 7Dh всегда как команду JGE.

1-й байт

2-й байт

Байты данных

Пример

7D

 

1

JGE aaaa

7.03-37 JL – переход, если меньше

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

Команда JL используется после выполнения операций над числами со знаком, в частности, после команд CMP, SBB, SUB (для чисел без знака условие "меньше" проверяет команда JB, 7.03-32).

Отладчик DEBUG.EXE принимает команду JL также под именем JNGE (Jump if Not Greater or Equal), но дизассемблирует код 7Ch всегда как команду JL.

1-й байт

2-й байт

Байты данных

Пример

7C

 

1

JL aaaa

7.03-38 JLE – переход, если меньше или равно

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

Команда JLE используется после выполнения операций над числами со знаком ,в частности, после команд CMP, SBB, SUB (для чисел без знака условие "меньше или равно" проверяет команда JBE, 7.03-33).

– 277 –

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

Отладчик DEBUG.EXE принимает команду JLE также под именем JNG (Jump if Not Greater), но тем не менее дизассемблирует код 7Eh всегда как команду JLE.

1-й байт

2-й байт

Байты данных

Пример

7E

 

1

JLE aaaa

7.03-39 JMP – безусловный переход

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

Пока процессор работает в реальном режиме, команда JMP состояния флагов не изменяет.

1-й байт

2-й байт

Байты

Примеры

Примечания

данных

 

 

 

 

E9

 

2

JMP ffff

*1

EA

 

4

JMP ffff:ffff

*2

EB

 

1

JMP aaaa

*1

FF

(2,6,A)(0-7)

0-2

JMP [bp+si+ffff]

*3

FF

(2,6,A)(8-F)

0-2

JMP FAR [bp+si+ffff]

*3

FF

E(0-7)

 

JMP bx

*4

Примечание 1: когда в ассемблерной команде JMP в качестве адреса перехода указано только смещение, отладчик DEBUG.EXE автоматически

вычисляет разность между этим смещением и смещением следующей машинной команды. Если полученная разность находится в пределах ±7Fh, то команда JMP транслируется в машинный код EBh "короткого" перехода, а иначе она транслируется в машинный код E9h "ближнего" перехода.

Примечание 2: в приведенном примере первое число это сегментный адрес перехода, второе число смещение. Указывать маркер "FAR" в такой строке вызова не обязательно: в любом случае будет выполнен дальний переход.

– 278 –

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