Описание процессора i8086 для программиста

         

AAA – коррекция сложения двоично-десятичных распакованных чисел


37

AAA

десятичная коррекция сложения AX

Описание.

Эта инструкция корректирует сумму двух распакованных двоично-десятичных чисел с целью получить двоично-десятичный распакованный результат. Она используется после инструкции ADD или ADC, выполняющей сложение, и корректирует результат, находящийся в регистре AL.

Если операция сложения сформировала признак вспомогательного переноса (флажок AF в регистре FLAGS был установлен) или если младший полубайт регистра AL содержит значение A16–F16, устанавливаются флажки AF и CF и производится инкремент регистра AH. Если же флажок AF был сброшен, а младший полубайт регистра AL содержал правильный десятичный код (значение 0–9), флажки AF и CF сбрасываются, а инкремент регистра AH не выполняется. В любом случае старший полубайт регистра AL обнуляется.

Флажки AF и CF устанавливаются в соответствии с результатом операции (см. выше).

Значение флажков OF, SF, ZF и PF не определено.



AAD – коррекция деления двоично-десятичных распакованных чисел




D50A

AAD

десятичная коррекция деления AX

Описание.

Эта команда используется для коррекции двоично-десятичного распакованного операнда, находящегося в регистре AX и используемого в последующей инструкции деления, для получения правильного двоичного результата.

В результате выполнения инструкции AAD

в регистре AL будет размещён двоичный эквивалент двоично-десятичного распакованного числа, находящегося перед этим в регистре AX (вычисляется по формуле AL:= AL + AH*10); содержимое регистра AH будет обнулено.

Флажки SF, ZF и PF устанавливаются по обычным правилам.

Значение флажков OF, AF и CF не определено.



AAM – коррекция умножения двоично-десятичных распакованных чисел


D4 0A

AAM

десятичная коррекция умножения AX

Описание.

Эта инструкция обеспечивает коррекцию результата умножения двух распакованных двоично-десятичных одноразрядных чисел командой MUL.

Коррекция заключается в том, что в регистр AH заносится целая часть от деления содержимого регистра AL на 10, а в регистр AL – остаток от этого деления.

Флажки SF, ZF и PF устанавливаются по обычным правилам.

Значение флажков OF, AF и CF не определено.



AAS – коррекция вычитания двоично-десятичных распакованных чисел


3F

AAS

десятичная коррекция вычитания AX

Описание.

Эта команда обеспечивает коррекцию результата вычитания двоично-десятичных распакованных одноразрядных чисел.

Если установлен флажок AF или содержимое младшего полубайта регистра AL превышает значение 9, из этого значения вычитается 6, содержимое регистра AH уменьшается на единицу и устанавливаются флажки AF и CF; в противном случае флажки AF и CF сбрасываются. В любом случае старший полубайт регистра AL обнуляется.

Флажки AF и CF устанавливаются, как описано выше.

Значение флажков OF, SF, ZF и PF не определено.



ADC – двоичное сложение с переносом


10 /r

ADC r/m8, r8

r/m8:= r/m8 + r8

+ CF

11 /r

ADC r/m16, r16

r/m16:= r/m16

+ r16 + CF

12 /r

ADC r8, r/m8

r8:= r8

+ r/m8 + CF

13 /r

ADC r16, r/m16

r16:= r16

+ r/m16 + CF

14 ib

ADC AL, imm8

AL:= AL + imm8 + CF

15 iw

ADC AX, imm16

AX:= AX + imm16 + CF

80 /2 ib

ADC r/m8, imm8

r/m8:= r/m8

+ imm8 + CF

81 /2 iw

ADC r/m16, imm16

r/m16:= r/m16

+ imm16 + CF

83 /2 ib

ADC r/m16, imm8

r/m16:= r/m16 + imm8 + CF

Описание.

Эта инструкция обеспечивает сложение двух 8- или 16-разрядных двоичных чисел с учётом значения входного переноса, определяемого флажком CF.

При сложении 16-разрядного первого операнда с 8-разрядным вторым (код операции 83) перед выполнением сложения производится расширение знака второго операнда.

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



ADD – двоичное сложение без переноса


00 /r

ADD r/m8, r8

r/m8:= r/m8 + r8

01 /r

ADD r/m16, r16

r/m16:= r/m16

+ r16

02 /r

ADD r8, r/m8

r8:= r8

+ r/m8

03 /r

ADD r16, r/m16

r16:= r16

+ r/m16

04 ib

ADD AL, imm8

AL:= AL + imm8

05 iw

ADD AX, imm16

AX:= AX + imm16

80 /0 ib

ADD r/m8, imm8

r/m8:= r/m8

+ imm8

81 /0 iw

ADD r/m16, imm16

r/m16:= r/m16

+ imm16

83 /0 ib

ADD r/m16, imm8

r/m16:= r/m16 + imm8

Описание.

Эта инструкция обеспечивает сложение двух 8- или 16-разрядных двоичных чисел. Результат помещается на место первого операнда.

При сложении 16-разрядного первого операнда с 8-разрядным вторым (код операции 83) перед выполнением сложения производится расширение знака второго операнда.

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



Адреса переходов


Различают переходы ближние (near, внутрисегментные) и дальние (far, межсегментные). Ближний переход осуществляется всегда в пределах текущего сегмента кода, т.е. содержимое регистра CS не изменяется. Дальний переход осуществляется в другой сегмент, т.е. при его выполняется изменяется содержимое не только указателя инструкции IP, но и регистра сегмента кода CS.

Инструкции безусловного перехода JMP и перехода к подпрограмме CALL

позволяют выполнять как ближние, так и дальние переходы. При ближних переходах используется относительная или косвенная адресация, при дальних – прямая или косвенная. Инструкции условных переходов и циклов осуществляют только ближние переходы, используя относительную адресацию.

При относительной адресации

код команды содержит в своём составе 8- или 16-разрядное отклонение.

Если переход происходит (т.е. если использована инструкция CALL

или JMP

либо если в инструкции условного перехода или цикла условие перехода соблюдается), отклонение складывается с адресом команды, расположенной сразу за данной инструкцией перехода, и полученная сумма заносится в регистр указателя инструкции IP. Значение селектора сегмента кода, находящееся в регистре CS, не изменяется. Таким образом, происходит переход относительно адреса команды, расположенной за инструкцией перехода, откуда данный вид адресации и получил своё название.

Команда JMP позволяет использовать 8- и 16-разрядные отклонения, что позволяет осуществлять переход либо в пределах от –128 до +127, либо от –65536 до –65535 байтов относительно следующей инструкции в пределах одного и того же сегмента. Первые переходы носят название коротких, вторые – длинных[3]. Команда CALL

использует только 16-разрядные отклонения. Инструкции условных переходов и циклов используют 8-разрядные отклонения. Таким образом, расстояние условного перехода оказывается весьма ограниченным, что иногда приводит к повышенному расходу памяти из-за необходимости использования пары команд – условного и безусловного перехода.


Часто отклонение, используемое при относительной адресации, называют смещением. Однако это может привести к путанице, поскольку термин “смещение” при программировании для микропроцессора 8086 используется в первую очередь для обозначения одной из двух частей логического адреса (см. подраздел 2.2.2 “Сегментация”). Термин “отклонение”, правда, тоже используется – для обозначения одного из компонентов эффективного адреса операнда, расположенного в памяти (см. параграф “Операнды в памяти” этого подраздела), однако значение этого термина оказывается в данном случае ближе к относительной адресации, поскольку и в том, и в другом случае отклонение фактически показывает, на сколько байтов в ту или иную сторону отстоит адресуемая ячейка от базового адреса, т.е. адреса следующей инструкции в команде относительного перехода или суммы содержимого регистров, используемых при формировании эффективного адреса операнда[4].

При прямой адресации код команды содержит полный адрес следующей выполняемой команды в формате “сегмент : смещение”, причём сначала располагается смещение, а потом – селектор сегмента. Прямая адресация используется инструкциями JMP

и CALL, позволяя передать им управление любой команде в памяти вычислительной машины.

Прямая адресация получила своё название в связи с тем, что в коде инструкции находится сам адрес перехода.

При косвенной адресации, доступной только инструкциям CALL и JMP, возможно выполнение как ближних, так и дальних переходов. В коде команды задаётся либо регистровый операнд (только для ближнего перехода), либо операнд в памяти (для ближнего или дальнего перехода), причём способ определения этого операнда не отличается от принятого для команд обработки данных (см. параграфы “Регистровые операнды” и “Операнды в памяти” этого подраздела).

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

Если выполняется дальний переход, адрес следующей инструкции занимает два слова памяти: в первом хранится смещение, а во втором – селектор сегмента, которые загружаются соответственно в регистры IP и CS. Сама команда перехода задаёт адрес первого их этих слов (операнд в памяти).

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


Адресация операндов


Большая часть инструкций имеет один или два явно заданных операнда. Операнды некоторых инструкций являются неявными, т.е. прямо в команде не указываются. Наконец, существуют инструкции, вообще не имеющие операндов.

Явно заданные операнды делятся на следующие группы:

– регистровые операнды;

– операнды в памяти;

– непосредственные операнды;

– адреса переходов.

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

Эффективное использование системы команд микропроцессора 8086 затрудняется “неортогональностью” применяемых способов адресации. Например, некоторые инструкции не допускают использования операндов в памяти или накладывают на их применение те или иные ограничения; в других невозможно использование непосредственных операндов; третьи используют в качестве операнда только один определённый регистр и не допускают применения других и т.д. В этом отношении разработки фирмы Intel существенно проигрывают появившимся за десятилетие до них мини-ЭВМ PDP-11 фирмы DEC, система команд которых намного удобнее и, несмотря на меньший набор команд, позволяет создавать значительно более эффективные программы[2].



AND – логическое И


20 /r

AND r/m8, r8

r/m8:= r/m8

AND r8

21 /r

AND r/m16, r16

r/m16:= r/m16 AND r16

22 /r

AND r8, r/m8

r8:= r8 AND r/m8

23 /r

AND r16, r/m16

r16:= r16 AND r/m16

24 ib

AND AL, imm8

AL:= AL AND imm8

25 iw

AND AX, imm16

AX:= AX AND imm16

80 /4 ib

AND r/m8, imm8

r/m8:= r/m8 AND imm8

81 /4 iw

AND r/m16, imm16

r/m16:= r/m16 AND imm16

Описание.

Выполняется операция “логическое И” между операндами инструкции, результат заносится на место первого операнда.

Флажки OF и CF очищаются.

Флажки SF, ZF и PF устанавливаются в соответствии с результатом.

Состояние флажка AF не определено.



Байт ModRegR/M


Основное назначение байта ModRegR/M – определять операнды, явно задаваемые в данной команде. Он состоит из трёх полей и имеет следующую структуру:

----T---T---T---T---T---T---T---¬

¦ M o d ¦   R e g   ¦   R / M   ¦

L---+---+---+---+---+---+---+----

7   6   5   4   3   2   1   0

Поле Mod определяет местоположение одного из операндов инструкции – в регистре или в памяти; в последнем случае совместно с полем R/M оно определяет способ вычисления эффективного адреса операнда (см. параграф “Операнды в памяти” подраздела 2.4.1 “Адресация операндов”).

Поле Reg либо указывает регистр, являющийся операндом инструкции, либо является расширением кода операции. Как номер регистра-операнда поле Reg используется только в инструкциях вида “регистр–регистр” или “регистр–память”; в инструкциях вида “регистр–непосредственный операнд”, а также в инструкциях, имеющих только один явно заданный операнд, это поле является частью кода операции.

Поле R/M содержит либо номер регистра–операнда инструкции, либо совместно с полем Mod определяет способ вычисления эффективного адреса операнда, находящегося в памяти. Интерпретация поля R/M зависит от содержимого поля Mod.

Кодировка регистров общего назначения в полях Reg и R/M осуществляется следующим образом:

– AX или AL – 000;

– CX или CL – 001;

– DX или DL – 010;

– BX или BL – 011;

– SP или AH – 100;

– BP или CH – 101;

– SI или DH – 110;

– DI или BH – 111.

Разрядность используемого регистра (8- или 16-разрядный) определяется кодом операции.

Местоположение операнда

определяется полями Mod и R/M следующим образом.

R/M

Mod

00

01

10

11

000

[BX+SI]

[BX+SI]+disp8

[BX+SI]+disp16

AX/AL

001

[BX+DI]

[BX+DI]+disp8

[BX+DI]+disp16

CX/CL

010

[BP+SI]

[BP+SI]+disp8

[BP+SI]+disp16

DX/DL

011

[BP+DI]

[BP+DI]+disp8

[BP+DI]+disp16

BX/BL

100

[SI]

[SI]+disp8

[SI]+disp16

SP/AH

101

[DI]

[DI]+disp8

[DI]+disp16

BP/CH

110

disp16

[BP]+disp8

[BP]+disp16

SI/DH

111

[BX]

[BX]+disp8

[BX]+disp16

DI/BH

<
Если поле Mod содержит значение 11, поле R/M определяет регистр общего назначения, являющийся операндом инструкции. Разрядность регистра зависит от разрядности выполняемой инструкции и определяется кодом операции.

Значения поля Mod, равные 00, 01 и 10, определяют операнд в памяти. Значение 00 указывает, что при вычислении эффективного адреса операнда отклонение не используется; значение 01 указывает, что используется 8-разрядное отклонение, находящееся в байте, следующем за байтом ModRegR/M; значение 10 указывает, что используется 16-разрядное отклонение, записанное в двух байтах, следующих за байтом ModRegR/M, в обычном порядке (“младший–старший”).

Поле R/M для случая операнда в памяти определяет, содержимое каких регистров общего назначения будет использоваться при вычислении эффективного адреса операнда.

Комбинация Mod=00 и R/M=110 является исключением из общего правила: эффективный адрес операнда равен 16-разрядному отклонению, следующему в коде команды непосредственно за байтом ModRegR/M; содержимое регистров общего назначения в формировании эффективного адреса для этого случая не используется.

Когда в состав эффективного адреса входит содержимое регистра BP, для формирования физического адреса операнда используется селектор сегмента стека, находящийся в регистре SS. Если же при вычислении эффективного адреса регистр BP не используется, физический адрес формируется с помощью селектора сегмента данных их регистра DS. И в том, и в другом случае используемый по умолчанию сегментный регистр может быть изменён с помощью префикса замены сегмента, входящего в состав кода команды.


CALL – вызов процедуры


9A cd

CALL ptr16:16

дальний переход к подпрограмме

E8 cw

CALL rel16

ближний переход к подпрограмме

FF /2

CALL r/m16

ближний косвенный переход к подпрограмме

FF /3

CALL m16:16

дальний косвенный переход к подпрограмме

Описание.

Адрес команды, следующей за инструкцией CALL, сохраняется в стеке. После этого происходит переход на первую команду вызываемой процедуры, адрес которой задан операндом инструкции CALL.

Команда CALL используется для выполнения как ближних (внутрисегментных), так и дальних (межсегментных) переходов. При ближнем переходе в стеке сохраняется только смещение следующей инструкции (содержимое регистра IP), при дальнем переходе сохраняется полный адрес – сначала содержимое регистра CS, а затем регистра IP.

Ближние переходы осуществляются с применением относительной (с 16-разрядным отклонением) и косвенной адресации, дальние – с применением прямой и косвенной адресации.

Флажки не изменяются.



CBW – преобразование байта в слово


98

CBW

расширение знака AL на AH

Описание.

Содержимое регистра AL, рассматриваемое как число со знаком, расширяется на регистр AH.

Если в AL содержалось отрицательное число (т.е. если старший разряд регистра AL равен 1), все разряды регистра AH устанавливаются в единицу. Если же в AL содержался нуль или положительное число (старший разряд регистра AL равен 0), регистр AH обнуляется.

Флажки не изменяются.



CLC – сброс флага переноса


F8

CLC

CF:= 0

Описание.

Флажок CF регистра FLAGS обнуляется.

Флажки не изменяются, за исключением флажка CF.



CLD – сброс флага направления


FC

CLD

DF:= 0

Описание.

Флажок DF регистра FLAGS обнуляется.

Когда флажок DF сброшен, строковые инструкции выполняются в направлении увеличения адресов памяти (производится автоинкремент регистров SI и DI).

Флажки не изменяются, за исключением флажка DF.



CLI – сброс флага разрешения прерывания


FA

CLI

IF:= 0

Описание.

Флажок IF регистра FLAGS обнуляется.

Когда флажок IF сброшен, маскируемые внешние прерывания запрещаются.

Флажки не изменяются, за исключением флажка IF.



CMC – инверсия флага переноса


F5

CMC

CF:=

NOT CF

Описание.

Флажок CF регистра FLAGS меняет своё значение на противоположное.

Флажки не изменяются, за исключением флажка CF.



CMP – сравнение


38 /r

CMP r/m8, r8

сравнение r/m8 и r8

39 /r

CMP r/m16, r16

сравнение r/m16 и r16

3A /r

CMP r8, r/m8

сравнение r8 и r/m8

3B /r

CMP r16, r/m16

сравнение r16 и r/m8

3C ib

CMP AL, imm8

сравнение AL и imm8

3D iw

CMP AX, imm16

сравнение AX и imm16

80 /7 ib

CMP r/m8, imm8

сравнение r/m8 и imm8

81 /7 iw

CMP r/m16, imm16

сравнение r/m16 и imm16

83 /7 ib

CMP r/m16, imm8

сравнение r/m16 и imm8

Описание.

Выполняется сравнение двух операндов.

Сравнение выполняется путём вычитания значения второго операнда из значения первого операнда. Результат вычитания теряется, однако на его основании устанавливаются те или иные флажки.

При выполнении операции над 16-разрядным первым операндом и 8-разрядным вторым (код операции 83) перед операцией производится расширение знака второго операнда.

Флажки

устанавливаются или сбрасываются в соответствии с результатом операции вычитания.



CMPS – сравнение строк


A6

CMPSB

сравнение байтов [DS:SI] и [ES:DI]

A7

CMPSW

сравнение слов [DS:SI] и [ES:DI]

Описание.

Эта инструкция сравнивает между собой байты или слова источника и приёмника.

Инструкция CMPS относится к группе инструкций обработки строк. Оба её операнда находятся в памяти. Адрес источника задаётся регистровой парой DS:SI, адрес приёмника – регистровой парой ES:DI. Сегментный регистр DS может быть заменён другим сегментным регистром с помощью префикса замены сегмента; сегментный регистр ES заменён быть не может.

После выполнения операции содержимое регистров SI и DI автоматически увеличивается или уменьшается на размер операнда, т.е. на 1 или на 2. Увеличение (автоинкремент) имеет место, если флажок направления DF в регистре флагов сброшен; уменьшение (автодекремент) – если флажок DF установлен.

Сравнение, как и в команде CMP, выполняется вычитанием значения приёмника из значения источника. Эти значения рассматриваются как двоичные числа со знаком. Результат вычитания теряется, исходные значения операндов не изменяются. По результатам вычитания устанавливаются соответствующие признаки в регистре флагов.

Инструкция CMPS выполняет сравнение одной пары байтов или слов. При необходимости вместе с ней могут использоваться префиксы повторения REP/REPcc, что обеспечит сравнение последовательностей байтов или слов памяти.

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



CWD – преобразование слово в двойное слово


99

CWD

Расширение знака AX на DX

Описание.

Содержимое регистра AX, рассматриваемое как число со знаком, расширяется на регистровую пару DX:AX. В регистр DX заносится старшая часть результата.

Если в AX содержалось отрицательное число (т.е. если старший разряд регистра AX равен 1), все разряды регистра DX устанавливаются в единицу. Если же в AX содержался нуль или положительное число (старший разряд регистра AX равен 0), регистр DX обнуляется.

Флажки не изменяются.



DAA – коррекция сложения двоично-десятичных упакованных чисел


27

DAA

двоично-десятичная коррекция сложения AL

Описание.

Эта команда выполняет коррекцию результата сложения двух двоично-кодированных десятичных чисел инструкцией ADD или ADC.

Если при выполнении предшествовавшей операции сложения в младшем полубайте регистра AL получено значение, превышающее 9, или произошёл перенос из 3-го разряда в 4-ый (был установлен флажок AF), то значение младшего полубайта регистра AL увеличивается на 6, флажок AF остаётся равным 1, а флажок CF устанавливается, если при прибавлении 6 возник перенос из 3-го разряда (если переноса не было, значение флажка CF не изменяется, т.е. остаётся таким же, каким оно было до выполнения инструкции DAA). Если же содержимое младшего полубайта регистра AL не превышает 9, а флажок AF сброшен, никаких действий с младшим полубайтом не выполняется.

Затем проверяется содержимое старшего полубайта регистра AL. Если его значение больше 9 либо если установлен флажок CF (независимо от того, был ли он установлен при выполнении команды сложения или при увеличении младшего полубайта на 6 в процессе выполнения инструкции DAA), то это значение увеличивается на 6 и устанавливается флажок CF. Если же значение старшего полубайта не превышает 9, а флажок CF сброшен, никаких действий со старшим полубайтом не выполняется.

Флажки AF и CF устанавливаются в соответствии с результатом операции (см. выше).

Флажки SF, ZF и PF устанавливаются по обычным правилам в соответствии с полученным результатом.

Значение флажка OF не определено.



DAS – коррекция вычитания двоично-десятичных упакованных чисел


2F

DAS

двоично-десятичная коррекция вычитания AL

Описание.

Эта команда выполняет коррекцию результата вычитания двух двоично-кодированных десятичных чисел инструкцией SUB или SBB.

Если при выполнении предшествовавшей операции вычитания в младшем полубайте регистра AL получено значение, превышающее 9, или произошёл заём в 3-ий разряд (был установлен флажок AF), то значение младшего полубайта регистра AL уменьшается на 6, флажок AF остаётся равным 1, а флажок CF устанавливается, если при вычитании 6 возник заём в 3-ий разряд (если заёма не было, значение флажка CF не изменяется, т.е. остаётся таким же, каким оно было до выполнения инструкции DAA). Если же содержимое младшего полубайта регистра AL не превышает 9, а флажок AF сброшен, никаких действий с младшим полубайтом не выполняется.

Затем проверяется содержимое старшего полубайта регистра AL. Если его значение больше 9 либо если установлен флажок CF (независимо от того, был ли он установлен при выполнении команды сложения или при уменьшении младшего полубайта на 6 в процессе выполнения инструкции DAS), то это значение уменьшается на 6 и устанавливается флажок CF. Если же значение старшего полубайта не превышает 9, а флажок CF сброшен, никаких действий со старшим полубайтом не выполняется.

Флажки AF и CF устанавливаются в соответствии с результатом операции (см. выше).

Флажки SF, ZF и PF устанавливаются по обычным правилам в соответствии с полученным результатом.

Значение флажка OF не определено.



DEC – декремент


48+rw

DEC r16

декремент r16

FE /1

DEC r/m8

декремент r/m8

FF /1

DEC r/m16

декремент r/m16

Описание.

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

Флажки OF, SF, ZF, AF и PF устанавливаются в соответствии с результатом по обычным правилам. Значение флажка CF не изменяется.



Действия микропроцессора по обработке прерывания


Независимо от причины возникновения прерывания микропроцессор обрабатывает их одинаковым образом.

Закончив выполнение инструкции, в ходе которого возник запрос прерывания, микропроцессор сохраняет в стеке текущее содержимое регистра флагов и дальний адрес текущей (для прерывания по ошибке деления) или следующей команды (для всех остальных причин возникновения прерывания), т.е. записывает в стек сначала содержимое регистра флагов, затем содержимое регистра CS, а в конце – содержимое регистра IP. Затем в регистре флагов сбрасывается флажки разрешения прерывания IF и трассировки TF, чем обеспечивается блокировка возникновения новых маскируемых внешних прерываний и запрещаются пошаговые прерывания по выполнении каждой инструкции. Наконец, из таблицы векторов прерываний извлекается дальний адрес обработчика прерывания, и его компоненты загружаются в регистры CS и IP, благодаря чему производится переход на обработку прерывания.

Следует обратить внимание на то, что, когда происходит немаскируемое прерывание, следующие немаскируемые прерывания блокируются аппаратурой микропроцессора до выполнения инструкции возврата из прерывания IRET. Маскируемые прерывания при этом также оказываются запрещены, но за счёт сброса флажка IF в регистре флагов. Если этот флажок будет установлен, микропроцессор будет способен обрабатывать маскируемые прерывания, хотя останется заблокированным для немаскируемых прерываний.



DIV – деление беззнаковое


F6 /6

DIV r/m8

AL:= AX DIV r/m8

AH:= AX MOD r/m8

F7 /6

DIV r/m16

AX:= DX, AX

DIV r/m16

DX:= DX, AX MOD r/m16

Описание.

Эта команда производит целочисленное деление двух беззнаковых двоичных чисел.

Делимое имеет размер 16 или 32 разряда. В первом случае оно располагается в регистре AX, во втором занимает регистровую пару DX:AX (старшая часть – в регистре DX, младшая – в регистре AX). Делитель размещается в регистре или ячейке памяти, определяемой байтом ModRegR/M. При 16-разрядном делимом делитель имеет размер байт, а при 32-разрядном делимом – слово.

Частное и остаток имеют разрядность, совпадающую с разрядностью делителя, т.е. в два раза меньше, чем у делимого. В операции деления 16-разрядного числа на 8-разрядное частное располагается в регистре AL, остаток – в регистре AH. При делении 32-разрядного числа на 16-разрядное частное будет находиться в регистре AX, а остаток – в регистре DX.

Если производится попытка деления на 0 или частное не помещается в отведённую разрядность, вырабатывается прерывание по ошибке деления (вектор 0).

Флажки не изменяются.



DS:/ES:/SS:/CS: – префиксы замены сегмента


26

ES:

использование сегмента ES

2E

CS:

использование сегмента CS

36

SS:

использование сегмента SS

3E

DS:

использование сегмента DS

Описание.

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

В инструкциях обработки данных с явно заданными операндами (например, MOV, ADD, NEG

и т.п.) один из операндов (или единственный операнд) может находиться в памяти. Для доступа к нему по умолчанию используется сегментный регистр SS (если при вычислении адреса операнда используется содержимое регистра BP) или сегментный регистр DS (во всех остальных случаях). С помощью префикса замены сегмента можно обратиться к операнду с использованием любого из четырёх сегментных регистров. Например, инструкция MOV AX,[BP] загружает в регистр AX содержимое слова памяти по адресу SS:BP, однако инструкция MOV AX,ES:[BP]

загрузит содержимое слова по адресу ES:BP.

В инструкциях обработки строк операнды адресуются с помощью регистровых пар DS:SI и ES:DI. Вместо сегментного регистра DS может использоваться любой сегментный регистр, для чего необходимо задать соответствующий префикс замены сегмента. Сегментный регистр ES, используемый совместно с регистром DI, заменён быть не может.

Доступ к стековой памяти с использованием указателя стека SP всегда подразумевает использование сегментного регистра SS, который подменён быть не может.



Двоично-десятичные числа


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

Команды сложения и вычитания позволяют обрабатывать упакованные и распакованные двоично-десятичные числа, команды умножения и вычитания – только распакованные числа. В любом случае одна инструкция обрабатывает один байт двоично-десятичных данных, причём на одну арифметическую инструкцию приходится одна инструкция коррекции.

Один байт двоично-десятичных распакованных данных хранит одну десятичную цифру. Код цифры (от 0 до 9 включительно в шестнадцатеричном виде) находится в младшем полубайте. Значение старшего полубайта при выполнении операций десятичной коррекции (AAA, AAD, AAM

и AAS) обнуляется.

В одном байте двоично-десятичных упакованных данных хранятся две десятичные цифры. Старшая цифра занимает старший полубайт, а младшая – младший полубайт. Каждая цифра кодируется шестнадцатеричным значением от 0 до 9 включительно.

Система команд микропроцессора 8086 слабо подходит для обработки двоично-десятичных данных, поэтому в реальных программах соответствующие инструкции и форматы данных используются весьма редко. Математический сопроцессор 8087 в данном случае более удобен, поскольку позволяет обрабатывать одной инструкцией двоично-десятичные упакованные числа с количеством десятичных разрядов 18, однако описание сопроцессора выходит за рамки настоящей книги.



Двоичные числа без знака


Процессор 8086 позволяет обрабатывать одно- и двухбайтовые двоичные числа без знака, покрывающие диапазон от 0 до 255 и от 0 до 65535 соответственно. Двухбайтовые величины называются словами.

Разряды чисел нумеруются слева направо. Таким образом, самый младший бит имеет номер 0, самый старший – 15 для двухбайтового числа и 7 для однобайтового.

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

Команда умножения двух 16-разрядных чисел даёт 32-разрядный результат, а команда деления обеспечивает деление 32-разрядного делимого на 16-разрядный делитель, при этом получаются 16-разрядные частное и остаток. Имеются также операции сдвига, работающие с 32-разрядными числами. 32-разрядные величины представляются двойными словами, состоящими из четырёх байтов.



Двоичные числа со знаком


Двоичные числа со знаком, обрабатываемые микропроцессором 8086, представлены в дополнительном коде, традиционном для всех современных вычислительных машин. Знаковым является старший разряд числа; нуль в этом разряде соответствует нулевому или положительному значению, единица – отрицательному значению. Покрываемый диапазон – от –128 до +127 для байтов и от –32768 до –32767 для слов.

Как и в случае с двоичными числами без знака, команды умножения, деления и сдвига могут иметь своими операндами не только 8- и 16-, но и 32-разрядные числа со знаком.



ESC – команда сопроцессора


11011xxxModRegR/M

ESC op, r/m

выполнение операции сопроцессора op над операндом r/m

Описание.

Эта команда обеспечивает выполнение заданной инструкции сопроцессора.

Процессор, обнаружив команду ESC (разряды 7-3 первого байта кода команды содержат комбинацию 11011), выдаёт сигнал обращения к сопроцессору. Сопроцессор фиксирует код своей операции, содержащийся в младших трёх разрядах байта кода команды. После этого основной процессор выбирает байт ModRegR/M и, если необходимо, один или два байта отклонения; формирует адрес операнда в памяти, если таковой задан байтом ModRegR/M, и выставляет его на шину адреса. Сопроцессор отслеживает этот процесс и при необходимости может читать или записывать данные в памяти по адресу, сформированному для него основным процессором. Кроме того, сопроцессор может интерпретировать поля байта ModRegR/M как номера его внутренних регистров или как расширения кода операции.

Поскольку операция сопроцессора может занять длительное время, основной процессор, завершив указанные выше действия, продолжает выполнение своей программы. Если необходимо дождаться завершения операции сопроцессора, после команды ESC

должна следовать команда WAIT.

Флажки не изменяются.



Физическая память


Память вычислительных машин на базе микропроцессора 8086 организована побайтно. Для адресации байтов используется 20-разрядный физический адрес. Адресация ведётся с нуля, максимальное шестнадцатеричное значение адреса – FFFFF.

Многобайтовые двоичные числа хранятся в смежных ячейках (байтах) памяти в порядке “младший–старший”, т.е. байт, содержащий самые младшие разряды числа, будет храниться в ячейке памяти с наименьшим адресом, а байт, содержащий самые старшие разряды – в ячейке с наибольшим адресом. Адресом всего числа является адрес его самого младшего байта.

Многобайтовые числа могут располагаться в памяти по любым адресам, какое-либо выравнивание не требуется. Однако производительность микропроцессора 8086, в отличие от микропроцессора 8088, повышается, если числа выровнены на их “естественную” границу, т.е. если слова (последовательности из двух байтов) хранятся по чётным адресам памяти. Это связано с тем, то микропроцессор 8086 имеет 16-разрядную шину данных, и для считывания или записи слова, хранящегося на чётной границе, ему достаточно одной операции доступа к памяти, в то время как для слова, хранящегося на нечётной границе, потребуются два доступа. Микропроцессор 8088, имея 16-разрядную внутреннюю архитектуру, располагает только 8-разрядной внешней шиной данных, поэтому для чтения или записи слова ему всегда потребуются две операции доступа к памяти.



Формат кода команды


Общая структура кодов большинства команд обработки данных микропроцессора 8086 следующая:

-----------¬ ----------¬ ------------¬ ---------------¬ ------------¬

¦ Prefixes ¦ ¦ Op Code ¦ ¦ ModRegR/M ¦ ¦ Displacement ¦ ¦ Immediate ¦

L----------- L---------- L------------ L--------------- L------------

Как видно из приведённого рисунка, код команды в общем случае состоит из пяти частей:

– префиксов (Prefixes) – 0–3 байта;

– кода операции (Op Code) – 1 байт;

– байта ModRegR/M – 1 байт;

– отклонения (Displacement) – 0–2 байта;

– непосредственного операнда (Immediate) – 0–2 байта.

В любой инструкции  присутствует код операции. Все остальные поля кода команды используются при возникновении такой необходимости. Длина кода команды колеблется от 1 до 9 байтов.

Инструкции переходов, использующие относительную адресацию, имеют следующий формат кода команды:

----------¬ ---------------¬

¦ Op Code ¦ ¦ Displacement ¦

L---------- L---------------

Код таких команд состоит из двух полей: однобайтового кода операции и отклонения длиной 1 или 2 байта в зависимости от используемой команды. Отклонение, рассматриваемое как число со знаком, прибавляется к содержимому указателя инструкции IP, который в этот момент указывает на команду, следующую за инструкцией перехода. В результате образуется адрес следующей команды.

Команды, использующие 8-разрядное отклонение, обеспечивают выполнение так называемых коротких переходов, а команды с 16-разрядным отклонением – длинных переходов. В любом случае переход является ближним (внутрисегментным).

Инструкции переходов, использующих прямую адресацию, имеют код команды размером 5 байт следующего формата:

----------¬ ---------¬ ----------¬

¦ Op Code ¦ ¦ Offset ¦ ¦ Segment ¦

L---------- L--------- L----------

Поля смещения (Offset) и селектора сегмента (Segment) занимают по два байта и вместе составляют адрес команды, на которую производится дальний (межсегментный) переход.

Формат инструкций перехода, использующих косвенную адресацию, сводится к общему формату команды обработки данных.
У них никогда не бывает поля непосредственного операнда, но всегда присутствует байт ModRegR/M; префиксы и отклонение могут присутствовать или отсутствовать. Если выполняется ближний (внутрисегментный) переход, т.е. если содержимое регистра CS не изменяется, смещение новой инструкции в текущем сегменте кода может содержаться либо в регистре общего назначения, либо в двухбайтовой области памяти, что определяется байтом ModRegR/M. Если же выполняется дальний (межсегментный) переход, то и новый селектор сегмента кода, и смещение находятся в четырёхбайтовой области памяти, адрес которой задаётся байтом ModRegR/M.

Некоторые инструкции имеют формат кода команды, отличающийся от вышеприведённых. Описание таких “нестандартных” форматов приводится при описании соответствующих инструкций.

Ниже более подробно рассматриваются компоненты кода команды обработки данных. Поля кодов инструкций переходов не рассматриваются, поскольку их назначение полностью ясно из приведённых выше рисунков и из описания в параграфе “Адреса переходов” подраздела 2.4.1 “Адресация операндов”.


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


F4

HLT

останов процессора

Описание.

По этой инструкции процессор прекращает дальнейшее выполнение операций и переходит в состояние останова.

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

Флажки не изменяются.



Идентификация источников прерываний


К сожалению, архитектура процессоров семейства 80x86 не позволяет однозначно идентифицировать источник прерывания по его вектору. Например, прерывание по вектору 0 может произойти по одной из следующих причин:

– по обнаружению ошибки во время выполнения инструкций деления DIV и IDIV (“штатная” причина для прерывания по этому вектору);

– по инструкции INT 0;

– при поступлении сигнала внешнего маскируемого прерывания, сопровождаемого передачей нулевого номера вектора прерывания[5].

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

Используемый в персональных компьютерах контроллер прерываний на базе микросхем типа 8259 (эмулируемый современными чипсетами) фиксирует факт обслуживания прерывания по каждой из своих линий запросов прерываний. Обработчик прерывания должен проверить состояние соответствующего внутреннего регистра контроллера прерываний, чтобы определить, послужил ли причиной прерывания внешний запрос или какое-нибудь событие внутри программы. Естественно, что если данному вектору прерывания не соответствует какая-либо линия запроса внешнего прерывания (IRQ), то и произойти это прерывание по внешнему запросу не может.

При прерывании по ошибке деления (вектор 0) сохранённый в стеке адрес будет указывать на команду деления, вызвавшую прерывание, в то время как при выполнении инструкции INT 0 – на следующую за ней инструкцию, которая также может оказаться командой деления. Необходимо проанализировать код команды, на которую указывает сохранённый в стеке адрес инструкции – если это не команда деления, то причиной прерывания является инструкция INT 0. Если же сохранён адрес команды деления, то требуется “ручная” проверка её параметров. Если они окажутся корректными, то прерывание возникло из-за инструкции INT 0, непосредственно предшествующей команде деления.
Если же параметры некорректны, причиной могла послужить и предшествовавшая инструкция INT 0, и инструкция деления. Совершенно однозначная идентификация в такой ситуации невозможна: хотя последние два байта, предшествующие команде деления, могут совпасть с кодом команды INT 0 (CD 00), нельзя поручиться, что эти байты не являются частью многобайтового кода какой-нибудь другой команды.

Чтобы определить, произошло ли прерывание по вектору 1 в результате трассировки выполнения программы с помощью флажка TF или из-за выполнения инструкции INT 1, нужно проверить состояние флажка TF в содержимом регистра FLAGS, сохранённом в стеке в процессе прерывания. Если этот флажок там сброшен, прерывание было вызвано инструкцией INT 1. Если же флажок был установлен, то имело место прерывание трассировки, что, однако, не исключает вероятности того, что одновременно была выполнена и инструкция INT 1. Однозначная идентификация в такой ситуации невозможна по той же причине, что и для вектора 0.

Прерывание по вектору 2 может произойти либо при поступлении внешнего сигнала немаскируемого прерывания NMI, либо при выполнении двухбайтовой команды INT 2. Однозначная идентификация возможна только в том случае, если аппаратура вычислительной машины обеспечивает программно-доступную фиксацию сведений о возникшем немаскируемом прерывании подобно тому, как контроллер прерываний 8259 при соответствующем программировании фиксирует информацию о маскируемых запросах прерываний по линиям IRQ.

Прерывания по векторам 3 и 4 могут быть программно идентифицированы однозначно: они происходят либо из-за выполнения однобайтовых инструкций INT3 и INTO

(коды CC и CE соответственно), либо из-за двухбайтовых инструкций INT 3 и INT 4

(коды CD 03 и CD 04 соответственно).

Таким образом, в общем случае абсолютно точно идентифицировать источник прерывания по векторам 0–2 невозможно. Как уже упоминалось, фирма Intel зарезервировала векторы 0–31 для “внутренних нужд” микропроцессора; часть из них задействована в современных образцах процессоров.Поэтому настоятельно не рекомендуется использовать инструкции INT

с номерами 0–31, а также назначать этим векторам маскируемые аппаратные прерывания.


IDIV – деление знаковое


F6 /7

IDIV r/m8

AL:= AX DIV r/m8

AH:= AX MOD r/m8

F7 /7

IDIV r/m16

AX:= DX, AX

DIV r/m16

DX:= DX, AX MOD r/m16

Описание.

Эта команда производит целочисленное деление двух двоичных чисел со знаком.

Делимое имеет размер 16 или 32 разряда. В первом случае оно располагается в регистре AX, во втором занимает регистровую пару DX:AX (старшая часть – в регистре DX, младшая – в регистре AX). Делитель размещается в регистре или ячейке памяти, определяемой байтом ModRegR/M. При 16-разрядном делимом делитель имеет размер байт, а при 32-разрядном делимом – слово.

Частное и остаток имеют разрядность, совпадающую с разрядностью делителя, т.е. в два раза меньше, чем у делимого. Знак остатка всегда совпадает со знаком делимого. В операции деления 16-разрядного числа на 8-разрядное частное располагается в регистре AL, остаток – в регистре AH. При делении 32-разрядного числа на 16-разрядное частное будет находиться в регистре AX, а остаток – в регистре DX.

Если производится попытка деления на 0 или частное не помещается в отведённую разрядность, вырабатывается прерывание по ошибке деления (вектор 0).

Флажки не изменяются.



IMUL – умножение знаковое


F6 /5

IMUL r/m8

AX:= AL * r/m8

F7 /5

IMUL r/m16

DX, AX:= AX * r/m16

Описание.

Эта команда производит целочисленное умножение двух двоичных чисел со знаком.

Один из множителей располагается в регистре AL или AX (в зависимости от разрядности), второй – в регистре общего назначения или ячейке памяти, что определяется байтом ModRegR/M.

Произведение имеет разрядность, вдвое превышающую разрядность множителей. Оно размещается в регистре AX (8-разрядные множители, 16-разрядный результат) или в регистровой паре DX:AX (16-разрядные множители, 32-разрядный результат, старшая часть в регистре DX, младшая – в AX).

Флажки SF, ZF, AF и PF не изменяются.

Флажки OF и CF устанавливаются, если разрядность результата превышает разрядность исходных операндов. Если результат вмещается в разрядность исходных операндов, эти флажки будут сброшены.



IN – ввод информации из порта ввода-вывода


E4 ib

IN AL, imm8

ввод в AL из порта imm8

E5 ib

IN AX, imm8

ввод в AX из порта imm8

EC

IN AL, DX

ввод в AL из порта [DX]

ED

IN AX, DX

ввод в AX из порта [DX]

Описание.

Эта инструкция вводит байт или слово данных из указанного порта ввода-вывода.

Если информация вводится из порта с адресом в диапазоне 0–FF16, номер порта может быть задан либо в самой команде, либо предварительно загружен в регистр DX. Для ввода информации из портов с номерами, превышающими FF16, может использоваться только косвенная адресация, когда номер порта предварительно загружен в регистр DX.

Информация, прочитанная из порта, заносится в регистр AL или AX в зависимости от её разрядности.

Флажки не изменяются.



INC – инкремент


FE /0

INC r/m8

инкремент r/m8

FF /0

INC r/m16

инкремент r/m16

40+rw

INC r16

инкремент r16

Описание.

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

Флажки OF, SF, ZF, AF и PF устанавливаются в соответствии с результатом по обычным правилам. Значение флажка CF не изменяется.



Инициализация процессора


Инициализация микропроцессора 8086 выполняется при поступлении аппаратного сигнала сброса. В результате выполнения внутренней микропрограммы сброса в регистрах устанавливаются следующие начальные значения (в шестнадцатеричном виде):

– регистр флагов Flags – F002;

– регистр указателя инструкции IP – 0000;

– регистр селектора сегмента кода CS – FFFF;

– регистр селектора сегмента данных DS – 0000;

– регистр селектора сегмента стека SS – 0000;

– регистр селектора сегмента дополнительных данных ES – 0000.

Содержимое других регистров микропроцессора непредсказуемо.

После установки начального содержимого перечисленных выше регистров микропроцессор производит выборку и выполнение первой инструкции. Её физический адрес равен FFFF0. В IBM-совместимых вычислительных машинах по этому адресу располагается ПЗУ BIOS, а первой выполняемой инструкцией является команда дальнего (межсегментного) безусловного перехода на программу самотестирования, являющуюся частью BIOS.



INT – программное прерывание


CC

INT 3

прерывание по вектору 3

CD ib

INT imm8

прерывание по вектору imm8

Описание.

Эта инструкция вырабатывает программное прерывание по указанному вектору.

Флажки в регистре флагов в момент записи его содержимого в стек имеют состояние на момент начала выполнения инструкции прерывания. В регистре флагов процессора после выполнения прерывания будут сброшены флажки IF и TF.



INTO – прерывание по переполнению


CE

INTO

генерация прерывания при OF=1

Описание.

Эта инструкция вырабатывает прерывание по вектору 4, если флажок переполнения OF установлен.

Флажки в регистре флагов в момент записи его содержимого в стек имеют состояние на момент начала выполнения инструкции прерывания. В регистре флагов процессора после выполнения прерывания будут сброшены флажки IF и TF.



IRET – возврат из прерывания


CF

IRET

возврат из прерывания

Описание.

Эта команда обеспечивает возврат из обработчика прерывания к прерванной программе.

Встретив инструкцию IRET, процессор выполняет следующие действия:

– восстанавливает из стека содержимое регистра IP;

– восстанавливает из стека содержимое регистра CS;

– восстанавливает из стека содержимое регистра флагов.

Флажки

восстанавливаются из стека.



Исключения


Микропроцессор 8086 обрабатывает три вида исключений – по ошибке деления, по точке остановка и по переполнению. Кроме того, в нём реализовано прерывание по трассировке.



Источники и причины прерываний


Прерывания в микропроцессоре 8086 могут возникать либо вследствие каких-либо внешний событий (внешние прерывания – external interrupts), либо из-за некоторых ошибок, возникающих в процессе выполнения программы (исключения – exceptions), либо генерироваться специальными инструкциями программы (программные прерывания – software interrupts).

Для определения обработчика прерывания, который должен быть выполнен, используется векторная система. Всего в микропроцессоре обеспечивается 256 различных векторов прерываний, из которых векторы 0–31 были зарезервированы фирмой Intel для “внутренних нужд” (в первых микропроцессорах – 8086 и 8088 – использовались только векторы 0–4; в дальнейшем их число росло). Векторы 32–255 могут свободно использоваться для нужд программного обеспечения, а также назначаться внешним устройствам.



Jcc – условные переходы


77 cb

JA rel8

переход, если выше (CF=0 и ZF=0)

73 cb

JAE rel8

переход, если выше или равно (CF=0)

72 cb

JB rel8

переход, если ниже (CF=1)

76 cb

JBE rel8

переход, если ниже или равно (CF=1 или ZF=1)

72 cb

JC rel8

переход, если есть перенос (CF=1)

E3 cb

JCXZ rel8

переход, если регистр CX содержит 0

74 cb

JE rel8

переход, если равно (ZF=1)

7F cb

JG rel8

переход, если больше (ZF=0 и SF=OF)

7D cb

JGE rel8

переход, если больше или равно (SF=OF)

7C cb

JL rel8

переход, если меньше (SF?OF)

7E cb

JLE rel8

переход, если меньше или равно (ZF=1 или SF?OF)

76 cb

JNA rel8

переход, если не выше (CF=1 или ZF=1)

72 cb

JNAE rel8

переход, если не выше или равно (CF=1)

73 cb

JNB rel8

переход, если не ниже (CF=0)

77 cb

JNBE rel8

переход, если не ниже или равно (CF=0 и ZF=0)

73 cb

JNC rel8

переход, если переноса нет (CF=0)

75 cb

JNE rel8

переход, если не равно (ZF=0)

7E cb

JNG rel8

переход, если не больше (ZF=1 или SF?OF)

7C cb

JNGE rel8

переход, если не больше или равно (SF?OF)

7D cb

JNL rel8

переход, если не меньше (SF=OF)

7F cb

JNLE rel8

переход, если не меньше или равно (ZF=0 и SF=OF)

71 cb

JNO rel8

переход, если переполнения нет (OF=0)

7B cb

JNP rel8

переход, если результат нечётный (PF=0)

79 cb

JNS rel8

переход, если знака нет (SF=0)

75 cb

JNZ rel8

переход, если не нуль (ZF=0)

70 cb

JO rel8

переход, если есть переполнение (OF=1)

7A cb

JP rel8

переход, если результат чётный (PF=1)

7A cb

JPE rel8

переход, если результат чётный (PF=1)

7B cb

JPO rel8

переход, если результат нечётный (PF=0)

78 cb

JS rel8

переход, если есть знак (SF=1)

74 cb

JZ rel8

переход, если нуль (ZF=1)

Описание.

Инструкции этого набора обеспечивают выполнение операций условных переходов. Условия, при которых осуществляется переход для той или иной инструкции, приведены в расположенной выше таблице.

Команды условных переходов используют относительную адресацию с 8-разрядным отклонением, что ограничивает длину перехода 127 байтами вперёд и 128 байтами назад относительно адреса команды, следующей за инструкцией условного перехода (так называемый короткий переход). Межсегментные переходы, как и переходы на более дальние расстояния внутри текущего сегмента, не обеспечиваются. Для этой цели должны использоваться пары инструкций условного и безусловного переходов.

Флажки не изменяются.



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


EB cb

JMP rel8

безусловный короткий переход

E9 cw

JMP rel16

безусловный ближний переход

FF /4

JMP r/m16

безусловный ближний косвенный переход

EA cd

JMP ptr16:16

безусловный дальний переход

FF /5

JMP m16:16

безусловный дальний косвенный переход

Описание.

Инструкция JMP

выполняет безусловный переход по указанному адресу.

Инструкция JMP обеспечивает ближние (внутрисегментные) и дальние (межсегментные) переходы. Ближние переходы осуществляются с применением относительной (с 8- или 16-разрядным отклонением) и косвенной адресации, дальние – с применением прямой и косвенной адресации.

Флажки не изменяются.



Код операции


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

Многие арифметико-логические инструкции способны обрабатывать данные размером байт или слово (два байта). Коды операций для этих команд отличаются значением младшего бита: нулевое значение соответствует обработке байтов, единичное – слов. В некоторых инструкциях часть кода операции входит в состав байта ModRegR/M, занимая в нём три разряда, соответствующие полю Reg.

Некоторые команды, предназначенные для обработки содержимого заданного регистра общего назначения, имеют однобайтовый код операции, старшие пять разрядов которого определяют операцию, а младшие три задают номер используемого регистра. Например, инструкция DEC AX

имеет код операции 48, инструкция DEC CX

– код операции 49 и т.п.

Полная сводка кодов операций микропроцессора 8086 приведена в приложении.



LAHF – загрузка флагов состояния в регистр AH


9F

LAHF

загрузка младшего байта регистра FLAGS в AL

Описание.

Содержимое младшего байта регистра флагов заносится в регистр AH.

Флажки не изменяются.



LDS – загрузка дальнего указателя для сегмента данных


C5 /r

LDS r16, m16:16

загрузка дальнего указателя в DS:r16

Описание.

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

В сегментный регистр из памяти заносится селектор сегмента. Смещение загружается в общий регистр, определяемый полем Reg байта ModRegR/M. Поля Mod и R/M этого байта указывают, где расположена область памяти, содержащая исходное значение указателя.

Флажки не изменяются.



LEA – загрузка эффективного адреса


8D /r

LEA r16, m

загрузка в r16 эффективного адреса ячейки m

Описание.

Вычисляется эффективный адрес операнда в памяти. Полученный результат заносится в регистр общего назначения.

Поля Mod и R/M байта ModRegR/M используются при вычислении эффективного адреса. Поле Reg этого байта определяет регистр общего назначения, в который эффективный адрес должен быть занесён.

Флажки не изменяются.



LES – загрузка дальнего указателя для дополнительного сегмента данных


C4 /r

LES r16, m16:16

загрузка дальнего указателя в ES:r16

Описание.

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

В сегментный регистр из памяти заносится селектор сегмента. Смещение загружается в общий регистр, определяемый полем Reg байта ModRegR/M. Поля Mod и R/M этого байта указывают, где расположена область памяти, содержащая исходное значение указателя.

Флажки не изменяются.



LOCK – блокировка шины


F0

LOCK

блокирование доступа к шине

Описание.

Префикс LOCK

заставляет процессор выставить на время выполнения следующей инструкции сигнал LOCK#, блокирующий доступ к памяти со стороны других процессоров и внешних устройств.

Префикс LOCK может использоваться только с инструкциями ADD, ADC, AND, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR

и XCHG.

Флажки префиксом не изменяются, но могут быть изменены инструкцией, с которым он используется.



LODS – загрузка строки


AC

LODSB

загрузка байта из [DS:SI] в AL

AD

LODSW

загрузка слова из [DS:SI] в AX

Описание.

Эта инструкция загружает в регистр AL или AX байт или слово по адресу DS:SI.

Инструкция LODS относится к группе инструкций обработки строк. Операнд-источник находится в памяти по адресу, содержащемуся в регистровой паре DS:SI. Сегментный регистр DS может быть заменён другим сегментным регистром с помощью префикса замены сегмента. Операндом-приёмником всегда является регистр AL или AX.

После загрузки байта или слова в аккумулятор содержимое регистра SI увеличивается (DF=0) или уменьшается (DF=1) на 1 или 2 в зависимости от размера операнда.

Флажки не изменяются.



LOOP/LOOPcc – цикл по счётчику в регистре CX


E2 cb

LOOP rel8

цикл по счётчику

E1 cb

LOOPE rel8

цикл по счётчику и равенству

E1 cb

LOOPZ rel8

цикл по счётчику и нулевому результату

E0 cb

LOOPNE rel8

цикл по счётчику и неравенству

E0 cb

LOOPNZ rel8

цикл по счётчику и ненулевому результату

Описание.

Команда LOOP

позволяет организовать цикл по счётчику, находящемуся в регистре CX.

Счётчик, в качестве которого всегда используется регистр CX, уменьшается на единицу. Если после этого счётчик не равен нулю, а дополнительное условие, если оно имеется, выполнено, производится переход на указанную команду. Если счётчик достиг нуля или если дополнительное условие не выполнено, переход не совершается.

Дополнительным условием продолжения выполнения цикла может быть нахождение флажка ZF в состоянии 0 (LOOPNE, LOOPNZ) или 1 (LOOPE, LOOPZ). Благодаря наличию такого условия упрощается программирование циклического анализа или сравнения каких-либо величин, когда условием завершения цикла является либо достижение конца обрабатываемых операндов (обнуление счётчика), либо выполнение условия неравенства или равенства, ненулевого или нулевого результата (установка флажка ZF в состояние 0 или 1).

Команда LOOP позволяет осуществлять только короткие переходы, поскольку в ней используется относительная адресация с 8-разрядным отклонением.

Флажки не изменяются.



Машинные инструкции


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

– NN+rb – код операции состоит из фиксированного кода NN (шестнадцатеричного), к которому прибавлен номер 8-разрядного регистра общего назначения;

– NN+rw – код операции состоит из фиксированного кода NN (шестнадцатеричного), к которому прибавлен номер 16-разрядного регистра общего назначения;

– /r – байт ModRegR/M, в котором поле Reg определяет номер регистра;

– /rцифра – байт ModRegR/M, в котором поле Reg имеет значение, указанное цифрой (например, /r2 означает, что поле Reg содержит двоичную комбинацию 010);

– cb – 8-разрядное отклонение;

– cw – 16-разрядное отклонение;

– cd – 32-разрядный абсолютный адрес дальнего перехода;

– ib – 8-разрядный непосредственный операнд;

– iw – 16-разрядный непосредственный операнд;

– imm8 – 8-разрядное непосредственное значение (константа);

– imm16 – 16-разрядное непосредственное значение (константа);

– ow – 16-разрядное смещение операнда в сегменте данных;

– r/m8 – 8-разрядный регистр общего назначения или байт памяти, определяемый полями Mod и R/M байта ModRegR/M. В коде команды может присутствовать 8- или 16-разрядное отклонение;

– r/m16 – 16-разрядный регистр общего назначения или слово памяти, определяемое полями Mod и R/M байта ModRegR/M. Операнд либо является арифметико-логическим, используемым в команде обработки данных, либо 16-разрядным смещением в команде абсолютного ближнего перехода. В коде команды может присутствовать 8- или 16-разрядное смещение;

– m8 – байт данных, заданный смещением (поле ow кода команды);

– m16 – слово данных, заданное смещением (поле ow кода команды);

– m16:16 – двойное слово памяти, содержащее селектор сегмента и смещение, используемые в качестве абсолютного адреса дальнего перехода. Местоположение поля в памяти определяется полями Mod и R/M байта ModRegR/M;

– r8 – 8-разрядный регистр общего назначения, определяемый полем Reg байта ModRegR/M;

– r16 – 16-разрядный регистр общего назначения, определяемый полем Reg байта ModRegR/M;

– Sreg – сегментный регистр, определяемый полем Reg байта ModRegR/M;

– rel8 – 8-разрядный относительный адрес ближнего перехода (8-разрядное отклонение);

– rel16 – 16-разрядный относительный адрес ближнего перехода (16-разрядное отклонение);

– ptr16:16 – абсолютный адрес дальнего перехода (16-разрядные селектор сегмента и смещение).

В сводке кодов команд указываются только обязательно присутствующие компоненты. Например, в арифметико-логических операциях, где один из операндов задаётся с помощью полей Mod и R/M байта ModRegR/M, не указывается поле отклонения, которое может присутствовать или отсутствовать в зависимости от содержимого байта ModRegR/M.



Маскируемые прерывания


Сигнал о запросе маскируемого прерывания поступает в микропроцессор по линии INT.

Выполнение текущей инструкции завершается обычным образом. В стеке будет сохранён адрес следующей инструкции.

Маскируемые прерывания могут быть запрещены средствами самого микропроцессора – для этого в регистре флагов должен быть сброшен флажок IF. В таком случае микропроцессор игнорирует сигнал на линии INT и продолжает выполнять инструкции в обычном порядке. Однако когда этот флажок установлен и поступает запрос маскируемого прерывания, микропроцессор завершает обычным образом выполнение текущей инструкции, после чего передаёт управление обработчику прерывания.

В отличие от немаскируемых прерываний, маскируемым не назначается какой-либо фиксированный вектор прерывания. Вместо этого микропроцессор, начиная процедуру выполнения маскируемого прерывания, выдаёт сигнал INTA, получив который, устройство, запросившее прерывание, выдаёт микропроцессору один байт информации, являющийся номером вектора прерывания, которое должно быть выполнено. Таким образом, для обработки маскируемых прерываний может использовать несколько (до 256) векторов.

Как правило, внешние устройства не выдают запросы прерываний напрямую микропроцессору, а передают их специальной микросхеме – контроллеру прерываний, который способен обслуживать запросы прерываний от нескольких устройств сразу и обеспечивает выдачу соответствующих векторов в микропроцессор. В первых персональных компьютерах использовалась одна микросхема типа 8259 (КР580ВН59 или КР1810ВН59А), обеспечивающая восемь векторов прерываний. В дальнейшем (начиная с машин серии IBM PC/AT) стали устанавливать две таких микросхемы, соединённых каскадно и обеспечивающих 15 прерываний. В современных компьютерах функции контроллера наряду со многими другими прерываний выполняют совершенно иные микросхемы, однако они эмулируют необходимые функции вышеназванных кристаллов. Тем не менее, сам микропроцессор не “навязывает” проектировщику аппаратуры обязанность использования отдельного контроллера прерывания. Можно, например, построить систему, где каждое устройство будет самостоятельно выдавать определённый для него вектор прерывания (правда, при этом придётся решить вопрос арбитража прерываний, т.е. найти способ определить, какое прерывание из нескольких, возникших одновременно, должно произойти).



MOV – пересылка


88 /r

MOV r/m8, r8

пересылка из r8 в r/m8

89 /r

MOV r/m16, r16

пересылка из r16 в r/m16

8A /r

MOV r8, r/m8

пересылка из r/m8 в r8

8B /r

MOV r16, r/m16

пересылка из r/m16 в r16

8C /r

MOV r/m16, Sreg

пересылка из Sreg в r/m16

8E /r

MOV Sreg, r/m16

пересылка из r/m16 в Sreg

A0 ow

MOV AL, m8

пересылка из m8 в AL

A1 ow

MOV AX, m16

пересылка из m16 в AX

A2 ow

MOV m8, AL

пересылка из AL в m8

A3 ow

MOV m16, AX

пересылка из AX в m16

B0+rb

MOV r8, imm8

пересылка imm8 в r8

B8+rw

MOV r16, imm16

пересылка imm16 в r16

C6 /0

MOV r/m8, imm8

пересылка imm8 в r/m8

C7 /0

MOV r/m16, imm16

пересылка imm16 в r/m16

Описание.

Команда MOV

пересылает содержимое источника (своего второго операнда) на место приёмника (первого операнда).

Инструкции с кодами операций 8C и 8E обеспечивают загрузку и извлечение информации из сегментных регистров. Занесение информации в регистр CS с помощью инструкции MOV невозможно, для этой цели необходимо использовать любую инструкцию дальнего (межсегментного) перехода.

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

Флажки не изменяются.



MOVS – пересылка строк


A4

MOVSB

пересылка байта из [DS:SI] в [ES:DI]

A5

MOVSW

пересылка слова из [DS:SI] в [ES:DI]

Описание.

Эта инструкция пересылает операнд-источник на место операнда-приёмника.

Инструкция MOVS относится к группе инструкций обработки строк. Оба её операнда находятся в памяти. Адрес источника задаётся регистровой парой DS:SI, адрес приёмника – регистровой парой ES:DI. Сегментный регистр DS может быть заменён другим сегментным регистром с помощью префикса замены сегмента; сегментный регистр ES заменён быть не может.

После выполнения операции содержимое регистров SI и DI автоматически увеличивается или уменьшается на размер операнда, т.е. на 1 или на 2. Увеличение (автоинкремент) имеет место, если флажок направления DF в регистре флагов сброшен, а уменьшение (автодекремент) – если флажок DF установлен.

За одно выполнение инструкции пересылается один байт или одно слово. Группа байтов или слов может быть переслана посредством использования префикса повторения REP.

Флажки не изменяются.



MUL – умножение беззнаковое


F6 /4

MUL r/m8

AX:= AL * r/m8

F7 /4

MUL r/m16

DX, AX:= AX * r/m16

Описание.

Эта команда производит целочисленное умножение двух беззнаковых двоичных чисел.

Один из множителей располагается в регистре AL или AX (в зависимости от разрядности), второй – в регистре общего назначения или ячейке памяти, что определяется байтом ModRegR/M.

Произведение имеет разрядность, вдвое превышающую разрядность множителей. Оно размещается в регистре AX (8-разрядные множители, 16-разрядный результат) или в регистровой паре DX:AX (16-разрядные множители, 32-разрядный результат, старшая часть в регистре DX, младшая – в AX).

Флажки SF, ZF, AF и PF не изменяются.

Флажки OF и CF устанавливаются, если разрядность результата превышает разрядность исходных операндов. Если результат вмещается в разрядность исходных операндов, эти флажки будут сброшены.



NEG – смена знака


F6 /3

NEG r/m8

r/m8:= – r/m8

F7 /3

NEG r/m16

r/m16:= – r/m16

Описание.

Эта команда меняет знак операнда противоположный.

Флажки OF, SF, ZF, AF и PF устанавливаются в соответствии с результатом.

Флажок CF сбрасывается, если исходный операнд равен нулю, и устанавливается в противном случае.



Немаскируемые прерывания


Микропроцессор извещается о возникновении немаскируемого запроса внешнего прерывания с помощью сигнала, поступающего по линии NMI. Получив этот сигнал, он обычным образом заканчивает выполнение очередной инструкции и выполняет процедуру прерывания по вектору 2, постоянно назначенному для немаскируемых прерываний. В стеке будет сохранён адрес следующей инструкции, т.е. инструкции, которая выполнялась бы, если бы не возникло прерывание.

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

Когда происходит немаскируемое прерывание, микропроцессор блокирует обработку новых запросов немаскируемых прерываний до тех пор, пока не будет выполнена инструкция возврата из прерывания IRET. Таким образом, несколько немаскируемых прерываний не могут быть “вложенными” друг в друга.

Как явствует из названия, это прерывание средствами самого микропроцессора не может быть замаскировано. Однако в персональных компьютерах обычно имеются внешние по отношению к микропроцессору схемы, позволяющие запретить немаскируемые прерывания путём блокировки прохождения сигнала по линии NMI.