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

         

Непосредственные операнды


Непосредственный операнд – это константа, задаваемая кодом команды. Он может иметь длину 1 или 2 байта в зависимости от разрядности выполняемой операции. Естественно, непосредственный операнд может быть только источником, но не приёмником результата.

Если приёмником в инструкции, использующей непосредственный операнд, является ячейка памяти, а не регистр общего назначения, может потребоваться использование указания BYTE PTR

или WORD PTR. Оно применяется в том случае, когда транслятор с языка ассемблера не может самостоятельно правильно определить разрядность операции. Например, в следующем примере первая команда обнулит байт памяти по смещению 1000h, а вторая – слово по тому же адресу (т.е. байты со смещениями 1000h и 1001h):

MOV   BYTE PTR 1000h, 0

MOV   WORD PTR 1000h, 0



Непосредственный операнд


8- или 16-разрядный непосредственный операнд присутствует только в командах вида “регистр–непосредственный операнд” и “память–непосредственный операнд”. Его наличие определяется кодом операции, который состоит из байта кода операции и поля Reg байта ModRegR/M. Поля Mod и R/M этого байта определяют местоположение второго операнда инструкции – в регистре общего назначения или в памяти.

Непосредственный операнд располагается в коде команды непосредственно за отклонением, а если последнее отсутствует – за байтом ModRegR/M. Байты 16-разрядного непосредственного операнда хранятся в порядке “младший–старший”.

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



NOP – нет операции


90

NOP



нет операции

Описание.

Никаких действий не производится.

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



NOT – инверсия


F6 /2

NOT r/m8

r/m8:= NOT r/m8

F7 /2

NOT r/m16

r/m16:= NOT r/m16

Описание.

Производится инверсия операнда.

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



Общие сведения


Процессор 8086 стал первым 16-разрядным микропроцессором, разработанным фирмой Intel. Он был выпущен в 1978 году и содержал 29 тыс. транзисторов (для сравнения: в первых Pentium’ах число транзисторов превышало 3 млн.). Почти одновременно был выпущен микропроцессор 8088. С точки зрения программиста, эти микропроцессоры абсолютно идентичны, однако микропроцессор 8086 имел 16-разрядную шину данных, а 8088 – 8-разрядную. Благодаря этому обстоятельству микропроцессор 8088 мог легко использоваться совместно с большим количеством разнообразных периферийных микросхем, разработанных к тому времени и ориентированных на работу с 8-разрядными микропроцессорами, в том числе с микропроцессором 8080 фирмы Intel (советский аналог – К580ВМ80). Однако его производительность оказывалась ощутимо меньше, чем у микропроцессора 8086, поскольку в процессе работы ему требовалось практически в два раза больше обращений к памяти.

16-разрядные микропроцессоры фирмы Intel позволяли адресовать до 1 Мбайта памяти, для чего с помощью механизма сегментации формировался 20-разрядный адрес памяти. Адресное пространство ввода-вывода достигало 64 Кбайт (адрес порта занимал 16 разрядов). Для сравнения: 8-разрядный микропроцессор 8080 был способен адресовать 64 Кбайта памяти и 256 портов ввода-вывода.

Процессоры 8086 и 8088 могли работать с максимальной тактовой частотой 8 МГц, обеспечивая быстродействие до 4 млн. операций в секунду. Фирма IBM, взявшись за разработку своего персонального компьютера, для ускорения и удешевления работы воспользовалась микропроцессором 8088, работающим с тактовой частотой всего 4,77 МГц, т.е. почти в два раза меньше предельно допустимой. Поэтому первые персональные компьютеры семейства IBM PC использовали далеко не все возможности, уже тогда предоставляемые микропроцессором.

Специально для работы совместно с микропроцессорами 8086/8088 предназначался математический сопроцессор 8087. Описание принципов его работы не входит в задачу данной книги.

Несколько западных фирм выпустили свои варианты процессоров 8086 и 8088. Некоторые из этих клонов имели расширенную систему команд, однако все они были совместимы “снизу вверх” с изделиями фирмы Intel. В СССР был выпущен микропроцессорный комплект К1810, в который входили микропроцессоры К1810ВМ86 и К1810ВМ88, полностью совпадающие со своими американскими прототипами, а также другие микросхемы, обеспечивающие работу процессоров в составе вычислительной системы и также являющиеся копиями аналогичных изделий фирмы Intel.

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



Операнды в памяти


Как уже отмечалось в подразделе 2.2.2 “Сегментация”, адрес памяти складывается из селектора сегмента и смещения. Смещение операнда в соответствующем сегменте называется эффективным адресом и вычисляется в процессе выполнения инструкции.

Для определения физического адреса явно заданного операнда, располагающегося в памяти, почти во всех случаях используется селектор сегмента, содержащийся в регистре сегмента данных DS. Исключением является лишь случай обращения к операнду, при вычислении эффективного адреса (смещения) которого используется содержимое регистра BP. В этом случае предполагается, что операнд располагается в сегменте стека, и используется селектор сегмента, хранящийся в регистре SS. В любом случае возможно использование префикса замены сегмента, явным образом определяющего, какой сегментный регистр содержит селектор, который должен использоваться при формировании физического адреса. На языке ассемблера префикс замены сегмента указывается с помощью мнемоники соответствующего сегментного регистра, предшествующей эффективному адресу операнда и отделяемой от него двоеточием. Например, в первой из следующих инструкций обращение осуществляется к сегменту данных, поскольку префикс замены сегмента не используется, а регистр BP в формировании эффективного адреса не участвует; во второй инструкции операнд находится в сегменте кода, поскольку сегмент задан явно. Эффективный адрес в обоих случаях является суммой содержимого регистра BX и константы 10h (называемой отклонением):

MOV   10h [BX], AX

MOV   CS:10h [BX], AX

Эффективный адрес формируется суммированием содержимого одного или двух регистров общего назначения и 8- или 16-разрядного отклонения (константы, задаваемой кодом команды). Эффективный адрес всегда имеет размер 16 бит; перенос из старшего разряда, если он возникает, игнорируется.

Первым из регистров, участвующих в формировании эффективного адреса, может быть регистр BX или BP, вторым – SI или DI. Другие регистры общего назначения в формировании эффективного адреса применяться не могут.


С любым из регистров или их комбинаций может использоваться 8- или 16-разрядное отклонение; отклонение может также отсутствовать. Исключением является случай использования регистра BP без регистра SI или DI: в такой ситуации всегда должно применяться 8- или 16-разрядное отклонение. Кроме того, эффективный адрес может быть задан 16-разрядным отклонением без использования каких-либо регистров.

На языке ассемблера регистр, участвующий в формировании эффективного адреса, заключается в квадратные скобки. Если применяются два регистра, то либо каждый из них заключается в свои собственные скобки, либо они находятся внутри одних скобок и соединяются там знаком “+”. Например, запись [BX][SI]

эквивалентна записи [BX+SI] и означает, что эффективный адрес является суммой содержимого регистров BX и SI.

Если эффективный адрес состоит из одного отклонения и это отклонение задаётся в числовом виде, а не как метка, перед ним обязательно должно стоять указание WORD PTR или BYTE PTR

в зависимости от того, имеет ли этот операнд размер слово или байт. Это требование связано с тем, что числовая величина будет воспринята транслятором языка ассемблера не как отклонение, а как непосредственный операнд (см. следующий подраздел). Таким образом, для занесения содержимого регистра BH в ячейку памяти со смещением 100h в сегменте данных необходимо использовать следующую инструкцию:

MOV   BYTE PTR 100h, BH

Если адресуемая ячейка памяти находится не в сегменте данных, указание BYTE PTR

или WORD PTR

не требуется, поскольку перед отклонением будет указан префикс замены сегмента, например:

MOV   ES:100h, BH

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

Способ формирования эффективного адреса определяется байтом ModRegR/M кода команды. Формат этого байта и назначение его полей будет описано ниже, в подразделе 2.4.2 “Формат кода команды”. Здесь отметим, что двухразрядное поле MOD определяет наличие и размер отклонения, а трёхразрядное поле R/M – используемую комбинацию регистров.Поле Reg в формировании эффективного адреса не участвует.


OR – логическое ИЛИ


08 /r

OR r/m8, r8

r/m8:= r/m8

OR r8

09 /r

OR r/m16, r16

r/m16:= r/m16 OR r16

0A /r

OR r8, r/m8

r8:= r8 OR r/m8

0B /r

OR r16, r/m16

r16:= r16 OR r/m16

0C ib

OR AL, imm8

AL:= AL OR imm8

0D iw

OR AX, imm16

AX:= AX OR imm16

80 /1 ib

OR r/m8, imm8

r/m8:= r/m8 OR imm8

81 /1 iw

OR r/m16, imm16

r/m16:= r/m16 OR imm16

Описание.

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

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

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

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



Отклонение


Отклонение является 8- или 16-разрядной величиной, используемой при вычислении эффективного адреса операнда. Один или два байта отклонения располагаются в коде команды сразу за байтом ModRegR/M; для 16-разрядного отклонения сначала идёт младший байт, а затем – старший. Наличие отклонения определяется содержимым байта ModRegR/M.

16-разрядное отклонение присутствует в двух случаях: когда поле Mod байта ModRegR/M содержит значение 10 либо когда поле Mod содержит значение 00, а поле R/M – значение 110.

8-разрядное отклонение присутствует, когда поле Mod содержит значение 01.



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


E6

ib

OUT AL, imm8

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

E7

ib

OUT AX, imm8

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

EE

OUT AL, DX

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

EF

OUT AX, DX

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

Описание.

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

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

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



POP – извлечение информации из стека


8F /0

POP m16

занесение данных из стека в m16

58+rw

POP r16

занесение данных из стека в r16

1F

POP DS

занесение данных из стека в DS

07

POP ES

занесение данных из стека в ES

17

POP SS

занесение данных из стека в SS

Описание.

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

Слово извлекается из вершины стека, адрес которой находится в регистровой паре SS:SP. После извлечения слова содержимое SP увеличивается на 2.

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



POPF – загрузка регистра флагов из стека


9D

POPF

загрузка слова из вершины стека в регистр FLAGS

Описание.

Эта инструкция извлекает из стека слово данных и заносит его в регистр FLAGS.

Слово извлекается из вершины стека, адрес которой находится в регистровой паре SS:SP. После извлечения слова содержимое SP увеличивается на 2.

Зарезервированные разряды регистра FLAGS не изменяются.

Флажки загружаются из стека.



Представление информации


Процессор 8086 оперирует 8- и 16-разрядными двоичными числами со знаком и без знака и строками символов длиной от 1 до 65536 символов. Кроме того, имеются команды десятичной коррекции, облегчающие обработку двоично-десятичных чисел.



Префиксы


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

Микропроцессор 8086 имеет 7 префиксов, делящихся на три группы. В коде одной команды могут присутствовать до трёх префиксов, обязательно относящихся к разным группам. Реакция микропроцессора на использование в команде нескольких префиксов из одной группы непредсказуема.

В первую группу входит единственный префикс блокировки шины LOCK

(шестнадцатеричный код префикса F0). Когда он присутствует в команде, на всё время выполнения инструкции системная шина захватывается данным микропроцессором, блокируя запросы к ней со стороны других процессоров многопроцессорной системы.

Во вторую группу входят префиксы повторения операции REP/REPE/REPZ

(F3) и REPNE/REPNZ (F2). Хотя для этой группы предусмотрено пять мнемоник, реально задействовано два кода префиксов. Они используются совместно со строковыми операциями с целью обработки нескольких байтов или слов одной командой.

Префиксы блокировки шины и повторения в программе на языке ассемблера располагаются непосредственно перед мнемоникой основной команды, совместно с которой они используются, например: LOCK OR [BX], AL.

К третьей группе относятся четыре префикса замены сегмента, имеющих следующие коды: 26 – сегмент ES, 2E – сегмент CS, 36 – сегмент SS, 3E – сегмент DS. В отличие от префиксов двух других групп, префиксы замены сегмента на языке ассемблера указываются уже после мнемоники основной команды и входят в состав операнда в памяти, сегмент которого они явно указывают, например: MOV ES:[BX], CX.

Некоторые сложности при программировании на языке ассемблера могут возникнуть при необходимости использовать префикс замены сегмента совместно со строковой операцией. Операнды строковых команд располагаются в сегментах DS и ES, причём заменить на другой можно только сегмент DS. Проблема заключается в том, что строковые инструкции не имеют явно задаваемых операндов, поэтому некуда включить префикс замены сегмента. Некоторые трансляторы с языка ассемблера, например MASM фирмы Microsoft и TASM фирмы Borland позволяют совместно с мнемоникой строковой операции указать формальные операнды, проверяемые синтаксически, но не играющие никакой роли при формировании кода операции. В этих операндах может быть указан и префикс замены сегмента. В некоторых случаях, однако, приходится вносить в программу непосредственно код префикса замены сегмента, предшествующий соответствующей строковой инструкции. Например, следующие две строки на языке ассемблера задают выполнение операции пересылки строк MOVSB с использованием префикса повторения REP

и префикса замены сегмента CS:

DB  2Eh

REP MOVSB



Прерывание по ошибке деления


Прерывание по ошибке деления возникает при выполнении инструкции DIV

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

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



Прерывание по переполнению


Прерывание по переполнению происходит, если при выполнении инструкции INTO

флажок переполнения OF в регистре флагов установлен. Когда этот флажок сброшен, инструкция INTO никаких действий не производит. Обработчик прерывания по переполнению использует вектор 4.

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



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


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

Следует обратить внимание, что система команд микропроцессора 8086 обеспечивает два формата инструкции INT3 – однобайтовый (код команды CC) и двухбайтовый (код команды CD 03). Функционально они ничем не отличаются, но двухбайтовый формат принято относить к программным прерываниям, а однобайтовый – к исключениям.



Прерывание по трассировке


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

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

в восстановленном содержимом регистра флагов флажок TF окажется установлен, то новое прерывание по трассировке произойдёт не сразу после выполнения инструкции IRET, а по завершении команды, на которую инструкцией IRET будет возвращено управление. В процессорах других ЭВМ, не обеспечивающих подобной задержки прерывания по трассировке, обычно используются две инструкции возврата из прерывания – одна для “обычного” возврата, другая – для возврата с задержкой прерывания по трассировке. Например, в 16-разрядных мини-ЭВМ семейства PDP-11 фирмы DEC (советский аналог – ЭВМ типа СМ-3, СМ-4, СМ-1420 и т.п.) имеются инструкции возврата из прерывания RTI

и RTT, отличающиеся друг от друга именно реакцией на флажок трассировки.



Коды операций


Код команды

Команда

1-й байт

2-й байт

3–6-й байты

Шестн.

Двоичный

00

00000000

ModRegR/M

[disp8/16]

ADD r/m8, r8

01

00000001

ModRegR/M

[disp8/16]

ADD r/m16, r16

02

00000010

ModRegR/M

[disp8/16]

ADD r8, r/m8

03

00000011

ModRegR/M

[disp8/16]

ADD r16, r/m16

04

00000100

imm8

ADD AL, imm8

05

00000101

imm16

ADD AX, imm16

06

00000110

PUSH ES

07

00000111

POP ES

08

00001000

ModRegR/M

[disp8/16]

OR r/m8, r8

09

00001001

ModRegR/M

[disp8/16]

OR r/m16, r16

0A

00001010

ModRegR/M

[disp8/16]

OR r8, r/m8

0B

00001011

ModRegR/M

[disp8/16]

OR r16, r/m16

0C

00001100

imm8

OR AL, imm8

0D

00001101

imm16

OR AX, imm16

0E

00001110

PUSH CS

0F

00001111

не используется

10

00010000

ModRegR/M

[disp8/16]

ADC r/m8, r8

11

00010001

ModRegR/M

[disp8/16]

ADC r/m16, r16

12

00010010

ModRegR/M

[disp8/16]

ADC r8, r/m8

13

00010011

ModRegR/M

[disp8/16]

ADC r16, r/m16

14

00010100

imm8

ADC AL, imm8

15

00010101

imm16

ADC AX, imm16

16

00010110

PUSH SS

17

00010111

POP SS

18

00011000

ModRegR/M

[disp8/16]

SBB r/m8, r8

19

00011001

ModRegR/M

[disp8/16]

SBB r/m16, r16

1A

00011010

ModRegR/M

[disp8/16]

SBB r8, r/m8

1B

00011011

ModRegR/M

[disp8/16]

SBB r16, r/m16

1C

00011100

imm8

SBB AL, imm8

1D

00011101

imm16

SBB AX, imm16

1E

00011110

PUSH DS

1F

00011111

POP DS

20

00100000

ModRegR/M

[disp8/16]

AND r/m8, r8

21

00100001

ModRegR/M

[disp8/16]

AND r/m16, r16

22

00100010

ModRegR/M

[disp8/16]

AND r8, r/m8

23

00100011

ModRegR/M

[disp8/16]

AND r16, r/m16

24

00100100

imm8

AND AL, imm8

25

00100101

imm16

AND AX, imm16

26

00100110

ES:

27

00100111

DAA

28

00101000

ModRegR/M

[disp8/16]

SUB r/m8, r8

29

00101001

ModRegR/M

[disp8/16]

SUB r/m16, r16

2A

00101010

ModRegR/M

[disp8/16]

SUB r8, r/m8

2B

00101011

ModRegR/M

[disp8/16]

SUB r16, r/m16

2C

00101100

imm8

SUB AL, imm8

2D

00101101

imm16

SUB AX, imm16

2E

00101110

CS:

2F

00101111

DAS

30

00110000

ModRegR/M

[disp8/16]

XOR r/m8, r8

31

00110001

ModRegR/M

[disp8/16]

XOR r/m16, r16

32

00110010

ModRegR/M

[disp8/16]

XOR r8, r/m8

33

00110011

ModRegR/M

[disp8/16]

XOR r16, r/m16

34

00110100

imm8

XOR AL, imm8

35

00110101

imm16

XOR AX, imm16

36

00110110

SS:

37

00110111

AAA

38

00111000

ModRegR/M

[disp8/16]

CMP r/m8, r8

39

00111001

ModRegR/M

[disp8/16]

CMP r/m16, r16

3A

00111010

ModRegR/M

[disp8/16]

CMP r8, r/m8

3B

00111011

ModRegR/M

[disp8/16]

CMP r16, r/m16

3C

00111100

imm8

CMP AL, imm8

3D

00111101

imm16

CMP AX, imm16

3E

00111110

SS:

3F

00111111

AAS

40

01000000

INC AX

41

01000001

INC CX

42

01000010

INC DX

43

01000011

INC BX

44

01000100

INC SP

45

01000101

INC BP

46

01000110

INC SI

47

01000111

INC DI

48

01001000

DEC AX

49

01001001

DEC CX

4A

01001010

DEC DX

4B

01001011

DEC BX

4C

01001100

DEC SP

4D

01001101

DEC BP

4E

01001110

DEC SI

4F

01001111

DEC DI

50

01010000

PUSH AX

51

01010001

PUSH CX

52

01010010

PUSH DX

53

01010011

PUSH BX

54

01010100

PUSH SP

55

01010101

PUSH BP

56

01010110

PUSH SI

57

01010111

PUSH DI

58

01011000

POP AX

59

01011001

POP CX

5A

01011010

POP DX

5B

01011011

POP BX

5C

01011100

POP SP

5D

01011101

POP BP

5E

01011110

POP SI

5F

01011111

POP DI

60

/

6F

01100000

/

01101111

не используются

70

01110000

rel8

JO rel8

71

01110001

rel8

JNO rel8

72

01110010

rel8

JB rel8

JNAE rel8

JC rel8

73

01110011

rel8

JNB rel8

JAE rel8

JNC rel8

74

01110100

rel8

JE rel8

JZ rel8

75

01110101

rel8

JNE rel8

JNZ rel8

76

01110110

rel8

JBE rel8

JNA rel8

77

01110111

rel8

JNBE rel8

JA rel8

78

01111000

rel8

JS rel8

79

01111001

rel8

JNS rel8

7A

01111010

rel8

JP rel8

JPE rel8

7B

01111011

rel8

JNP rel8

JPO rel8

7C

01111100

rel8

JL rel8

JNGE rel8

7D

01111101

rel8

JNL rel8

JGE rel8

7E

01111110

rel8

JLE rel8

JNG rel8

7F

01111111

rel8

JNLE rel8

JG rel8

80

10000000

Mod000R/M

[disp8/16] imm8

ADD r/m8, imm8

Mod001R/M

[disp8/16] imm8

OR r/m8, imm8

Mod010R/M

[disp8/16] imm8

ADC r/m8, imm8

Mod011R/M

[disp8/16] imm8

SBB r/m8, imm8

Mod100R/M

[disp8/16] imm8

AND r/m8, imm8

Mod101R/M

[disp8/16] imm8

SUB r/m8, imm8

Mod110R/M

[disp8/16] imm8

XOR r/m8, imm8

Mod111R/M

[disp8/16] imm8

CMP r/m8, imm8

81

10000001

Mod000R/M

[disp8/16] imm8

ADD r/m16, imm16

Mod001R/M

[disp8/16] imm8

OR r/m16, imm16

Mod010R/M

[disp8/16] imm8

ADC r/m16, imm16

Mod011R/M

[disp8/16] imm8

SBB r/m16, imm16

Mod100R/M

[disp8/16] imm8

AND r/m16, imm16

Mod101R/M

[disp8/16] imm8

SUB r/m16, imm16

Mod110R/M

[disp8/16] imm8

XOR r/m16, imm16

Mod111R/M

[disp8/16] imm8

CMP r/m16, imm16

82

10000010

не используется

83

10000011

Mod000R/M

[disp8/16] imm8

ADD r/m16, imm8

xx001xxx

не используется

Mod010R/M

[disp8/16] imm8

ADC r/m16, imm8

Mod011R/M

[disp8/16] imm8

SBB r/m16, imm8

xx100xxx

не используется

Mod101R/M

[disp8/16] imm8

SUB r/m16, imm8

xx110xxx

не используется

xx111xxx

не используется

84

10000100

ModRegR/M

[disp8/16]

TEST r/m8, r8

85

10000101

ModRegR/M

[disp8/16]

TEST r/m16, r16

86

10000110

ModRegR/M

[disp8/16]

XCHG r/m8, r8

87

10000111

ModRegR/M

[disp8/16]

XCHG r/m16, r16

88

10001000

ModRegR/M

[disp8/16]

MOV r/m8, r8

89

10001001

ModRegR/M

[disp8/16]

MOV r/m16, r16

8A

10001010

ModRegR/M

[disp8/16]

MOV r8, r/m8

8B

10001011

ModRegR/M

[disp8/16]

MOV r16, r/m16

8C

10001100

Mod0SRR/M

[disp8/16]

MOV r/m16, Sreg

xx1xxxxx

не используется

8D

10001101

ModRegR/M

[disp8/16]

LEA r16, m

8E

10001110

Mod0SRR/M

[disp8/16]

MOV r/m16, Sreg

xx1xxxxx

не используется

8F

10001111

Mod000R/M

[disp8/16]

POP r/m16

xx001xxx

/

xx111xxx

не используется

90

10010000

NOP (XCHG AX, AX)

91

10010001

XCHG AX, CX

92

10010010

XCHG AX, DX

93

10010011

XCHG AX, BX

94

10010100

XCHG AX, SP

95

10010101

XCHG AX, BP

96

10010110

XCHG AX, SI

97

10010111

XCHG AX, DI

98

10011000

CBW

99

10011001

CWD

9A

10011010

ptr16:16

CALL ptr16:16

9B

10011011

WAIT

9C

10011100

PUSHF

9D

10011101

POPF

9E

10011110

SAHF

9F

10011111

LAHF

A0

10100000

m8

MOV AL, m8

A1

10100001

m16

MOV AX, m16

A2

10100010

m8

MOV m8, AL

A3

10100011

m16

MOV m16, AX

A4

10100100

MOVSB

A5

10100101

MOVSW

A6

10100110

CMPSB

A7

10100111

CMPSW

A8

10101000

imm8

TEST AL, imm8

A9

10101001

imm16

TEST AX, imm16

AA

10101010

STOSB

AB

10101011

STOSW

AC

10101100

LODSB

AD

10101101

LODSW

AE

10101110

SCASB

AF

10101111

SCASW

B0

10110000

imm8

MOV AL, imm8

B1

10110001

imm8

MOV CL, imm8

B2

10110010

imm8

MOV DL, imm8

B3

10110011

imm8

MOV BL, imm8

B4

10110100

imm8

MOV AH, imm8

B5

10110101

imm8

MOV CH, imm8

B6

10110110

imm8

MOV DH, imm8

B7

10110111

imm8

MOV BH, imm8

B8

10111000

imm16

MOV AX, imm16

B9

10111001

imm16

MOV CX, imm16

BA

10111010

imm16

MOV DX, imm16

BB

10111011

imm16

MOV BX, imm16

BC

10111100

imm16

MOV SP, imm16

BD

10111101

imm16

MOV BP, imm16

BE

10111110

imm16

MOV SI, imm16

BF

10111111

imm16

MOV DI, imm16

C0

11000000

не используется

C1

11000001

не используется

C2

11000010

imm16

RET imm16 (ближний)

C3

11000011

RET

(ближний)

C4

11000100

ModRegR/M

[disp8/16]

LES r16, m16:16

C5

11000101

ModRegR/M

[disp8/16]

LDS r16, m16:16

C6

11000110

Mod000R/M

[disp8/16] imm8

MOV m8, imm8

xx001xxx

/

xx111xxx

не используется

C7

11000111

Mod000R/M

[disp8/16] imm16

MOV m16, imm16

xx001xxx

/

xx111xxx

не используется

C8

11001000

не используется

C9

11001001

не используется

CA

11001010

imm16

RET imm16 (дальний)

CB

11001011

RET (дальний)

CC

11001100

INT 3

CD

11001101

imm8

INT imm8

CE

11001110

INTO

CF

11001111

IRET

D0

11010000

Mod000R/M

[disp8/16]

ROL r/m8, 1

Mod001R/M

[disp8/16]

ROR r/m8, 1

Mod010R/M

[disp8/16]

RCL r/m8, 1

Mod011R/M

[disp8/16]

RCR r/m8, 1

Mod100R/M

[disp8/16]

SAL r/m8, 1

SHL r/m8, 1

Mod101R/M

[disp8/16]

SHR r/m8, 1

xx110xxx

не используется

Mod111R/M

[disp8/16]

SAR r/m8, 1

D1

11010001

Mod000R/M

[disp8/16]

ROL r/m16, 1

Mod001R/M

[disp8/16]

ROR r/m16, 1

Mod010R/M

[disp8/16]

RCL r/m16, 1

Mod011R/M

[disp8/16]

RCR r/m16, 1

Mod100R/M

[disp8/16]

SAL r/m16, 1

SHL r/m16, 1

Mod101R/M

[disp8/16]

SHR r/m16, 1

xx110xxx

не используется

Mod111R/M

[disp8/16]

SAR r/m16, 1

D2

11010010

Mod000R/M

[disp8/16]

ROL r/m8, CL

Mod001R/M

[disp8/16]

ROR r/m8, CL

Mod010R/M

[disp8/16]

RCL r/m8, CL

Mod011R/M

[disp8/16]

RCR r/m8, CL

Mod100R/M

[disp8/16]

SAL r/m8, CL

SHL r/m8, CL

Mod101R/M

[disp8/16]

SHR r/m8, CL

xx110xxx

не используется

Mod111R/M

[disp8/16]

SAR r/m8, CL

D3

11010011

Mod000R/M

[disp8/16]

ROL r/m16, CL

Mod001R/M

[disp8/16]

ROR r/m16, CL

Mod010R/M

[disp8/16]

RCL r/m16, CL

Mod011R/M

[disp8/16]

RCR r/m16, CL

Mod100R/M

[disp8/16]

SAL r/m16, CL

SHL r/m16, CL

Mod101R/M

[disp8/16]

SHR r/m16, CL

xx110xxx

не используется

Mod111R/M

[disp8/16]

SAR r/m16, CL

D4

11010100

AAM

D5

11010101

AAD

D6

11010110

не используется

D7

11010111

XLATB

D8

/

DF

11011xxx

ModRegR/M

[disp8/16]

ESC

E0

11100000

rel8

LOOPNE rel8

LOOPNZ rel8

E1

11100001

rel8

LOOPE rel8

LOOPZ rel8

E2

11100010

rel8

LOOP rel8

E3

11100011

rel8

JCXZ rel8

E4

11100100

imm8

IN AL, imm8

E5

11100101

imm8

IN AX, imm8

E6

11100110

imm8

OUT AL, imm8

E7

11100111

imm8

OUT AX, imm8

E8

11101000

rel16

CALL rel16

E9

11101001

rel16

JMP rel16

EA

11101010

ptr16:16

JMP ptr16:16

EB

11101011

rel8

JMP rel8

EC

11101100

IN AL, DX

ED

11101101

IN AX, DX

EE

11101110

OUT AL, DX

EF

11101111

OUT AX, DX

F0

11110000

LOCK

F1

11110001

не используется

F2

11110010

REPNE

REPNZ

F3

11110011

REP

REPE

REPZ

F4

11110100

HLT

F5

11110101

CMC

F6

11110110

Mod000R/M

[disp8/16] imm8

TEST r/m8, imm8

xx001xxx

не используется

Mod010R/M

[disp8/16]

NOT r/m8

Mod011R/M

[disp8/16]

NEG r/m8

Mod100R/M

[disp8/16]

MUL r/m8

Mod101R/M

[disp8/16]

IMUL r/m8

Mod110R/M

[disp8/16]

DIV r/m8

Mod111R/M

[disp8/16]

IDIV r/m8

F7

11110111

Mod000R/M

[disp8/16] imm8

TEST r/m16, imm16

xx001xxx

не используется

Mod010R/M

[disp8/16]

NOT r/m16

Mod011R/M

[disp8/16]

NEG r/m16

Mod100R/M

[disp8/16]

MUL r/m16

Mod101R/M

[disp8/16]

IMUL r/m16

Mod110R/M

[disp8/16]

DIV r/m16

Mod111R/M

[disp8/16]

IDIV r/m16

F8

11111000

CLC

F9

11111001

STC

FA

11111010

CLI

FB

11111011

STI

FC

11111100

CLD

FD

11111101

STD

FE

11111110

Mod000R/M

[disp8/16]

INC r/m8

Mod001R/M

[disp8/16]

DEC r/m8

xx010xxx

/

xx111xxx

не используется

FF

11111111

Mod000R/M

[disp8/16]

INC r/m16

Mod001R/M

[disp8/16]

DEC r/m16

Mod010R/M

[disp8/16]

CALL r/m16

Mod011R/M

[disp8/16]

CALL m16:16

Mod100R/M

[disp8/16]

JMP r/m16

Mod101R/M

[disp8/16]

JMP m16:16

Mod110R/M

[disp8/16]

PUSH r/m16

xx111xxx

не используется



Время выполнения команд


В этом приложении приведено время выполнения команд и прерываний в машинных тактах для микропроцессора 8086 (КР1810ВМ86). Для микропроцессора 8088 время выполнения многих команд будет больше, поскольку ему требуется больше обращений к памяти.

Во многих командах общее время выполнения складывается из некоторого “базового” количества тактов плюс количества, необходимого для вычисления эффективного адреса.

Время вычисления эффективного адреса

Поле R/M

Mod=00

Mod=01

Mod=10

адресация

такты

адресация

такты

адресация

такты

000

BX+SI

7

BX+SI+disp8

11

BX+SI+disp16

BX+SI+disp8

001

BX+DI

8

BX+DI+disp8

12

BX+DI+disp16

BX+DI+disp8

010

BP+SI

8

BP+SI+disp8

12

BP+SI+disp16

BP+SI+disp8

011

BP+DI

7

BP+DI+disp8

11

BP+DI+disp16

BP+DI+disp8

100

SI

5

SI+disp8

9

SI+disp16

SI+disp8

101

DI

5

DI+disp8

9

DI+disp16

DI+disp8

110

disp16

6

BP+disp8

9

BP+disp16

BP+disp8

111

BX

5

BX+disp8

9

BX+disp16

BX+disp8

Время выполнения команд

Команда

Такты

AAA

4

AAD

60

AAS

4

AAM

83

ADC r, r

3

    r, m

9+EA

    m, r

16+EA

    r, imm

4

    m, imm

17+EA

ADD r, r

3

    r, m

9+EA

    m, r

16+EA

    r, imm

4

    m, imm

17+EA

AND r, r

3

    r, m

9+EA

    m, r

16+EA

    r, imm

4

    m, imm

17+EA

CALL rel16

19

     r16

16

     m16

21+EA

     ptr16:16

28

     m16:16

37+EA

CBW

2

CLC

2

CLD

2

CLI

2

CMC

2

CMP r, r

3

    r, m

9+EA

    m, r

9+EA

    r, imm

4

    m, imm

10+EA

CMPS

22

REP CMPS

9+22*N

CWD

5

DAA

4

DAS

4

DEC r16

2

    r8

3

    m

15+EA

DIV r8

80–90

    r16

144–162

    m8

(86–96)+EA

    m16

(150–168)+EA

ESC op, r

2

    op, m

8+EA

HLT

2

IDIV r8

101–112

     r16

165–184

     m8

(107–118)+EA

     m16

(171–190)+EA

IMUL r8

80–98

     r16

128–154

     m8

(86–104)+EA

     m16

(134–160)+EA

IN acc, imm8

10

   acc, DX

8

INC r16

2

    r8

3

    m

15+EA

INT 3

51

    imm8

52

INTO

4/53

IRET

24

Jcc rel8

4/16

JCXZ rel8

6/18

JMP rel8/16

15

    r16

11

    m16

18+EA

    ptr16:16

15

    m16:16

24+EA

LAHF

4

LDS r16, m16:16

16+EA

LEA r16, m

2+EA

LES r16, m16:16

16+EA

LODS

12

LOOP rel8

5/17

LOOPE rel8

LOOPZ rel8

6/18

LOOPNE rel8

LOOPNZ rel8

5/19

MOV m, acc

10

    acc, m

10

    sr, r16

2

    sr, m16

8+EA

    r16, sr

2

    m16, sr

9+EA

    r, r

2

    r, m

8+EA

    m, r

9+EA

    r, imm

4

    m, imm

10+EA

MOVS

18

REP MOVS

9+17*N

MUL r8

70–77

    r16

118–133

    m8

(76–83)+EA

    m16

(124–139)+EA

NEG r

3

    m

16+EA

NOP

3

NOT r

3

    m

16+EA

OR r, r

3

   r, m

9+EA

   m, r

16+EA

   r, imm

4

   m, imm

17+EA

OUT acc, imm8

10

    acc, DX

8

POP r16

8

    m16

17+EA

    sr

8

POPF

8

PUSH r16

11

     m16

16+EA

     sr

10

PUSHF

10

сдвиг r, 1

2

      m, 1

15+EA

      r, CL

8+4*N

      m, CL

20+EA+4*N

RET (ближний)

8

    imm16 (ближний)

12

    (дальний)

17

    imm16 (дальний)

18

SAHF

4

SBB r, r

3

    r, m

9+EA

    m, r

16+EA

    r, imm

4

    m, imm

17+EA

SCAS

15

REP SCAS

9+15*N

STC

2

STD

2

STI

2

STOS

11

REP STOS

9+10*N

SUB r, r

3

    r, m

9+EA

    m, r

16+EA

    r, imm

4

    m, imm

17+EA

TEST r, r

3

     r, m

9+EA

     m, r

9+EA

     acc, imm

4

     r, imm

5

     m, imm

11+EA

WAIT

3+5*N

XCHG AX, r16

3

     r16, AX

3

     r, r

4

     r, m

17+EA

     m, r

17+EA

XLAT

11

XOR r, r

3

    r, m

9+EA

    m, r

16+EA

    r, imm

4

    m, imm

17+EA

Префиксы команд

LOCK

2

REP/REPcc

2

замены сегмента

2

Прерывания

внешние

61

немаскируемые

50

трассировки

50

<
 

В таблице EA – время вычисления эффективного адреса; N – число повторений операции.

[1]

Позднее, при разработке микропроцессора 80286, инженеры фирмы Intel допустили ошибку, из-за чего этот перенос учитывался. Ошибка не была вовремя замечена, и в персональные компьютеры пришлось вводить дополнительные схемы, позволяющие либо блокировать 20-ю линию адреса (чтобы сохранялась совместимость с процессором 8086), либо разрешать её нормальное функционирование (для использования областей памяти с физическими адресами свыше FFFFF16). Эта ошибка из соображений совместимости повторяется и во всех последующих процессорах.

[2]

Примером может служить многозадачная многопользовательская операционная система реального времени RSX-11, способная эффективно работать на ЭВМ с объёмом памяти 128 Кбайт, обеспечивая при этом истинную многозадачность, защиту памяти и предоставляя пользователю куда более широкий набор функций, чем MS DOS, хотя последняя является однозадачной и при этом намного более требовательна к объёму памяти. Начиная с микропроцессора 80386, фирма Intel значительно улучшила эффективность системы команд, но так и не смогла “подтянуть” её даже до уровня PDP-11, не говоря уже о 32-разрядной супермини-ЭВМ VAX-11.

[3]

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

[4]

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

[5]

Не следует путать номера векторов прерываний, т.е. местоположение адреса программы-обработчика прерывания в таблице векторов прерываний, с номером аппаратного прерывания, т.е. номером линии запроса прерывания, поступающего контроллеру прерываний (номером IRQ).Соответствие между номерами линий прерываний (IRQ) и номерами векторов задаётся при программировании контроллера прерываний и, вообще говоря, к архитектуре микропроцессора прямого отношения не имеет.


Приоритет прерываний


Одновременно может возникать несколько запросов прерываний. В этом случае микропроцессор обслуживает их в соответствии с их приоритетами. Сначала обслуживается прерывание с высшим приоритетом, затем – с более низким (если в результате обслуживания более приоритетного запроса процессор не оказался замаскирован для менее приоритетного прерывания).

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

Следом по приоритету следует немаскируемое внешнее прерывание. Как уже отмечалось, если такое прерывание произошло, следующее немаскируемое прерывание может быть выполнено только после выполнения команды IRET, при этом не играет роли, обработку какого запроса прерывания данная команда завершает (аппаратура микропроцессора реагирует на сам факт выполнения инструкции IRET).

На третьем месте стоят маскируемые внешние прерывания. Поскольку выполнение прерывания приводит к сбросу флажка IF в регистре флагов, выполнение маскируемого прерывания откладывается до тех пор, пока флажок IF не будет вновь установлен.

Самый низкий приоритет имеет трассировочное прерывание.



Программные прерывания


Программные прерывания возникают при выполнении инструкций INT n, где n

– номер вектора прерывания, которое должно произойти. Коды этих команд состоят из двух байтов: первый содержит код операции (CD), второй – номер вектора прерывания. При прерывании в стеке сохраняется адрес следующей инструкции.



PUSH – занесение информации в стек


FF /6

PUSH r/m16

занесение данных в стек из r/m16

58+rw

PUSH r16

занесение данных в стек из r16

06

PUSH ES

занесение в стек ES

0E

PUSH CS

занесение в стек CS

16

PUSH SS

занесение в стек SS

1E

PUSH DS

занесение в стек DS

Описание.

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

Содержимое SP уменьшается на два, после чего по полученному адресу производится запись заданного слова данных.

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



PUSHF – запись регистра флагов в стек


9C

PUSHF

запись в стек содержимого регистра FLAGS

Описание.

Эта инструкция заносит в вершину стека содержимое регистра FLAGS.

Перед записью содержимое SP уменьшается на два. Регистр флагов записывается по полученному адресу.

Зарезервированные разряды регистра FLAGS не изменяются.

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



RCL – циклический сдвиг влево через флажок переноса


D0 /2

RCL r/m8, 1

циклический сдвиг r/m8 влево на 1 разряд через CF

D2 /2

RCL r/m8, CL

циклический сдвиг r/m8 влево на CL разрядов через CF

D1 /2

RCL r/m16, 1

циклический сдвиг r/m16 влево на 1 разряд через CF

D3 /2

RCL r/m16, CL

циклический сдвиг r/m16 влево на CL разрядов через CF

Описание.

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

Сдвиг выполняется по следующей схеме:

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

¦ ---¬     ----------¬  ¦

L-+CF¦<----+ операнд ¦<--

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

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

Флажок CF содержит значение последнего выдвинутого из операнда разряда.

Значение флажка OF в операции многоразрядного сдвига не определено. В операции одноразрядного сдвига он представляет собой результат операции “исключающее ИЛИ” между значением старшего разряда результата и содержимым флажка CF после выполнения сдвига. Таким образом, единичное значение флажка OF свидетельствует о том, что содержимое старшего разряда результата отличается от его исходного значения, а нулевое значение – что старший разряд операнда не изменился.

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



RCR – циклический сдвиг вправо через флажок переноса


D0 /3

RCR r/m8, 1

циклический сдвиг r/m8 вправо на 1 разряд через CF

D2 /3

RCR r/m8, CL

циклический сдвиг r/m8 вправо на CL разрядов через CF

D1 /3

RCR r/m16, 1

циклический сдвиг r/m16 вправо на 1 разряд через CF

D3 /3

RCR r/m16, CL

циклический сдвиг r/m16 вправо на CL разрядов через CF

Описание.

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

Сдвиг выполняется по следующей схеме:

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

¦  ---¬     ----------¬ ¦

L->¦CF+---->¦ операнд +--

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

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

Флажок CF содержит значение последнего выдвинутого из операнда разряда.

Значение флажка OF в операции многоразрядного сдвига не определено. В операции одноразрядного сдвига он представляет собой результат операции “исключающее ИЛИ” между содержимым двух самых старших разрядов результата. Таким образом, единичное значение флажка OF указывает, что операнд сменил свой знак, а нулевое – что знак остался неизменным.

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



Регистр флагов


В состав микропроцессора входит 16-разрядный регистр флагов, обозначаемый Flags. Он состоит из отдельных разрядов, имеющих самостоятельное значение. Формат регистра Flags и назначение его битов приведено ниже.

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

¦ 1 ¦ 1 ¦ 1 ¦ 1 ¦ OF

¦ DF

¦ IF

¦ TF

¦ SF

¦ ZF

¦ 0 ¦ AF

¦ 0 ¦ PF

¦ 1 ¦ CF

¦

L---+---+---+---+----+----+----+----¦----+----+---+----+---+----+---+-----

15                                                                   0

Разряды 15-12, 5, 3 и 1 не используются. При записи они должны содержать значения, показанные на приведённом выше рисунке. В последующих микропроцессорах (80286, 80386 и т.д.) часть этих разрядов была задействована для выполнения новых функций.

OF (разряд 11) – флаг переполнения. Он устанавливается в арифметических операциях, свидетельствуя о возникновении переполнения при обработке чисел со знаком.

DF (разряд 10) – флаг направления. Нулевое значение этого флага соответствует обработке строковых операндов в порядке возрастания их адресов, единичное – в порядке убывания.

IF (разряд 9) – флаг разрешения прерывания. Нулевое значение этого флага запрещает обработку маскируемых прерываний, единичное – разрешает.

TF (разряд 8) – флаг трассировки. Когда он установлен, после выполнения каждой инструкции микропроцессора происходит прерывание, используемое обычно в отладочных целях. Когда этот флаг сброшен, прерывание по окончании инструкции не возникает.

SF (разряд 7) – флаг знака. Изменяется большинством арифметико-логических команд. Нулевое значение показывает, что в операции над числами со знаком было получено неотрицательное число, единичное значение – что результатом является отрицательное число. Таким образом, этот флаг повторяет значение старшего (знакового) разряда результата.

ZF (разряд 6) – флаг нуля. Изменяется большинством арифметико-логических команд. Этот флаг сбрасывается в нуль, если результат операции отличен от нуля, и устанавливается, если результат равен нулю.


AF (разряд 4) – флаг вспомогательного переноса. Устанавливается в командах сложения и вычитания при возникновении переноса из третьего или заёма в третий разряд соответственно. Этот флаг используется командами десятичной коррекции DAA

и DAS.

PF (разряд 2) – флаг чётности. Устанавливается, если младший байт результата операции содержит чётное число единичных разрядов, сбрасывается в противном случае.

CF (разряд 0) – флаг переноса. Устанавливается при возникновении переноса или заёма из/в старший разряд результата при выполнении команд сложения и вычитания, а также содержит значение выдвигаемого разряда в операциях сдвига.

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

Содержимое регистра флагов целиком доступно только для инструкций PUSHF

и POPF, которые соответственно сохраняют его значение в стеке или извлекают из стека. Младший байт регистра Flags может быть загружен в регистр AH инструкцией LAHF, содержимое регистра AH может быть переслано в младший байт регистра Flags посредством инструкции SAHF. Кроме того, при возникновении прерывания состояние регистра Flags сохраняется в стеке. Инструкция IRET, обеспечивающая возврат из прерывания, подобно инструкции POPF восстанавливает содержимое регистра флагов из стека.

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

Для арифметико-логических команд содержимое регистра Flags напрямую недоступно.


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


В командах обработки данных регистры общего назначения могут использоваться для хранения значений операндов. В этом случае говорят о регистровой адресации. Например, команда MOV AX,BX

пересылает содержимое регистра BX в регистр AX.

Сегментные регистры могут использоваться в качестве операндов только в некоторых командах пересылки, а именно в инструкциях MOV, PUSH

и POP. Сегментный регистр CS может служит источником в инструкции MOV, но не может служить приёмником. Он не может также использоваться в команде POP.

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



Регистры микропроцессора


С точки зрения программиста микропроцессор 8086 включает следующие регистры:

– регистры общего назначения;

– сегментные регистры;

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

– регистр указателя инструкции.



Регистры общего назначения


Процессор 8086 имеет восемь 16-разрядных регистров общего назначения, обозначаемых AX, BX, CX, DX, SI, DI, BP и SP.

Старший и младший байты регистров AX, BX, CX и DX могут использоваться отдельно. Они носят обозначения AH, BH, CH и DH для старших байтов и AL, BL, CL и DL для младших байтов.

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

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

Регистр BX используется при адресации операндов.

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

Регистр DX расширяет разрядность регистра AX в операциях умножения, деления и двойного сдвига; он содержит адрес порта ввода-вывода в инструкциях ввода-вывода.

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

Регистр DI содержит смещение строки-приёмника в строковых операциях и может использоваться при адресации операндов.

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

Регистр SP является указателем стека.



REP/REPcc – повторение строковой операции


F3 A4

REP MOVSB

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

F3 A5

REP MOVSW

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

F3 AC

REP LODSB

загрузка CX байтов из DS:SI в AL

F3 AD

REP LODSW

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

F3 AA

REP STOSB

запись CX байтов из AL в ES:DI

F3 AB

REP STOSW

запись CX слов из AX в ES:DI

F3 A6

REPE CMPSB

сравнение CX байтов в DS:SI и ES:DI до несовпадения

F3 A7

REPE CMPSW

сравнение CX слов в DS:SI и ES:DI до несовпадения

F3 AE

REPE SCASB

поиск байта, отличающегося от AL, в CX байтах в ES:DI

F3 AF

REPE SCASW

поиск слова, отличающегося от AX, в CX словах в ES:DI

F2 A6

REPNE CMPSB

сравнение CX байтов в DS:SI и ES:DI до совпадения

F2 A7

REPNE CMPSW

сравнение CX слов в DS:SI и ES:DI до совпадения

F2 AE

REPNE SCASB

поиск байта, совпадающего с AL, в CX байтах в ES:DI

F2 AF

REPNE SCASW

поиск слова, совпадающего с AX, в CX словах в ES:DI

Описание.

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

Счётчик находится в регистре CX. После каждого выполнения инструкции, употреблённой с префиксом повторения, содержимое CX уменьшается на единицу и проверяется на равенство нулю. Если нуль ещё не достигнут, снова выполняется инструкция, уменьшается и проверяется CX и т.д. Если же в результате вычитания содержимое CX обнулилось, операция прекращается. Таким образом, операция может быть повторена от одного до 65536 раз.

Помимо завершения операции по обнулению счётчика, в некоторых инструкциях предусмотрено её завершение при выполнении определённого условия, а именно равенства или неравенства флажка ZF нулю.

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

– простое повторение – префикс REP, код операции F3; операция заканчивается, когда содержимое регистра CX обнуляется;


– повторение, пока соблюдается равенство – префикс REPE/REPZ, код операции F3; операция заканчивается, когда содержимое регистра CX обнуляется или когда сбрасывается флажок ZF;

– повторение, пока равенство не соблюдается – префикс REPNE/REPNZ, код операции F2; операция заканчивается, когда содержимое регистра CX обнуляется или когда устанавливается флажок ZF.

С инструкциями MOVS, LODS, STOS

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

С инструкциями CMPS и SCAS употребляются префиксы REPE/REPZ

и REPNE/REPNZ. Первый префикс обеспечивает прекращение операции при исчерпании счётчика или при сбросе флажка ZF в нуль; последнее событие имеет место, когда обнаружено неравенство сравниваемых байтов или слов. Второй префикс обеспечивает прекращение операции при исчерпании счётчика или при установке флажка ZF в единицу, что происходит при обнаружении равенства сравниваемых байтов или слов.

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


RET – возврат из процедуры


C3

RET

Ближний возврат из процедуры

CB

RET

Дальний возврат из процедуры

C2 iw

RET imm16

Ближний возврат из процедуры с очисткой стека

CA iw

RET imm16

Дальний возврат из процедуры с очисткой стека

Описание.

Инструкция RET

обеспечивает возврат из процедуры.

Адрес возврата должен храниться в вершине стека. Для операции ближнего возврата он занимает два байта, для операции дальнего возврата – четыре байта. Процессор извлекает адрес возврата и заносит его в регистры CS (только при дальнем возврате) и IP, при этом содержимое указателя стека SP увеличивается на 2 или 4.

Разновидность инструкции RET, обеспечивающая очистку стека, дополнительно прибавляет к содержимому SP указанную в инструкции 16-разрядную величину, что освобождает в стеке заданное число байтов.

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



ROL – циклический сдвиг влево


D0 /0

ROL r/m8, 1

циклический сдвиг r/m8 влево на 1 разряд через CF

D2 /0

ROL r/m8, CL

циклический сдвиг r/m8 влево на CL разрядов через CF

D1 /0

ROL r/m16, 1

циклический сдвиг r/m16 влево на 1 разряд через CF

D3 /0

ROL r/m16, CL

циклический сдвиг r/m16 влево на CL разрядов через CF

Описание.

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

Сдвиг выполняется по следующей схеме:

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

---¬  ¦ ----------¬  ¦

¦CF¦<-+-+ операнд

¦<--

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

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

Флажок CF содержит значение последнего выдвинутого из операнда разряда.

Значение флажка OF в операции многоразрядного сдвига не определено. В операции одноразрядного сдвига он представляет собой результат операции “исключающее ИЛИ” между значением старшего разряда результата и содержимым флажка CF после выполнения сдвига. Таким образом, единичное значение флажка OF свидетельствует о том, что содержимое старшего разряда результата отличается от его исходного значения, а нулевое значение – что старший разряд операнда не изменился.

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



ROR – циклический сдвиг вправо


D0 /1

ROR r/m8, 1

циклический сдвиг r/m8 вправо на 1 разряд через CF

D2 /1

ROR r/m8, CL

циклический сдвиг r/m8 вправо на CL разрядов через CF

D1 /1

ROR r/m16, 1

циклический сдвиг r/m16 вправо на 1 разряд через CF

D3 /1

ROR r/m16, CL

циклический сдвиг r/m16 вправо на CL разрядов через CF

Описание.

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

Сдвиг выполняется по следующей схеме:

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

¦  ----------¬ ¦  ---¬

L->¦ операнд +-+->¦CF¦

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

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

Флажок CF содержит значение последнего выдвинутого из операнда разряда.

Значение флажка OF в операции многоразрядного сдвига не определено. В операции одноразрядного сдвига он представляет собой результат операции “исключающее ИЛИ” между содержимым двух самых старших разрядов результата. Таким образом, единичное значение флажка OF указывает, что операнд сменил свой знак, а нулевое – что знак остался неизменным.

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



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


9E

SAHF

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

Описание.

Значащие разряды младшего байта регистра FLAGS устанавливаются в соответствии с соответствующими разрядами регистра AH. Содержимое зарезервированных разрядов (битов 1, 3 и 5) не изменяется.

Флажки

устанавливаются в соответствии с содержимым AH.



SAL – арифметический сдвиг влево


D0 /4

SAL r/m8, 1

арифметический сдвиг r/m8 влево на 1 разряд

D2 /4

SAL r/m8, CL

арифметический сдвиг r/m8 влево на CL разрядов

D1 /4

SAL r/m16, 1

арифметический сдвиг r/m16 влево на 1 разряд

D3 /4

SAL r/m16, CL

арифметический сдвиг r/m16 влево на CL разрядов

Описание.

Эта инструкция производит арифметический (он же логический – см. инструкцию SHL) сдвиг содержимого своего операнда влево на указанное вторым операндом число разрядов.

Сдвиг выполняется по следующей схеме:

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

¦CF¦<--+ операнд ¦<- 0

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

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

Флажок CF содержит значение последнего выдвинутого из операнда разряда.

Значение флажка OF в операции многоразрядного сдвига не определено. В операции одноразрядного сдвига он представляет собой результат операции “исключающее ИЛИ” между значением старшего разряда результата и содержимым флажка CF после выполнения сдвига. Таким образом, единичное значение флажка OF свидетельствует о том, что содержимое старшего разряда результата отличается от его исходного значения, а нулевое значение – что старший разряд операнда не изменился.

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

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



SAR – арифметический сдвиг вправо


D0 /7

SAR r/m8, 1

арифметический сдвиг r/m8 вправо на 1 разряд

D2 /7

SAR r/m8, CL

арифметический сдвиг r/m8 вправо на CL разрядов

D1 /7

SAR r/m16, 1

арифметический сдвиг r/m16 вправо на 1 разряд

D3 /7

SAR r/m16, CL

арифметический сдвиг r/m16 вправо на CL разрядов

Описание.

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

Сдвиг выполняется по следующей схеме:

----¬

¦  -+--------¬   ---¬

L->¦ операнд +-->¦CF¦

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

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

Флажок CF содержит значение последнего выдвинутого из операнда разряда.

Флажок OF сбрасывается, поскольку при арифметическом сдвиге вправо состояние старшего (знакового) разряда операнда никогда не изменяется.

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



SBB – двоичное вычитание с заёмом


18 /r

SBB r/m8, r8

r/m8:= r/m8 – r8

– CF

19 /r

SBB r/m16, r16

r/m16:= r/m16

– r16 – CF

1A /r

SBB r8, r/m8

r8:= r8

– r/m8 – CF

1B /r

SBB r16, r/m16

r16:= r16 –

r/m16 – CF

1C ib

SBB AL, imm8

AL:= AL – imm8 – CF

1D iw

SBB AX, imm16

AX:= AX – imm16 – CF

80 /3 ib

SBB r/m8, imm8

r/m8:= r/m8

– imm8 – CF

81 /3 iw

SBB r/m16, imm16

r/m16:= r/m16

– imm16 – CF

83 /3 ib

SBB r/m16, imm8

r/m16:= r/m16 – imm8 – CF

Описание.

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

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

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



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


AE

SCASB

поиск байта AL в [ES:DI]

AF

SCASW

поиск слова AX в [ES:DI]

Описание.

Эта инструкция производит поиск байта или слова, содержащегося в регистре AL/AX, в строке по адресу [ES:DI].

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

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

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

Флажки изменяются в соответствии с результатами выполнения сравнения.



Сегментация


Микропроцессор 8086 для формирования 20-разряного физического адреса использует 16-разрядные селекторы сегментов и смещения.

Селекторы сегментов

хранятся в сегментных регистрах (см. подраздел 2.3.2 “Сегментные регистры”). В зависимости от того, с какой целью выполняется обращение к памяти, процессор использует один из четырёх имеющихся селекторов сегментов. Так, если обращение производится для выборки кода команды, используется селектор сегмента кода, хранящийся в регистре CS, а если происходит запись данных в стек – селектор сегмента стека из регистра SS.

Смещение

формируется в процессе выполнения команды и определяет местоположение требуемой информации внутри сегмента. Например, при выборке кода команды производится чтение байта памяти, хранящегося по смещению из регистра IP (см. подраздел 2.3.4 “Указатель инструкции”) в сегменте кода, селектор которого находится в регистре CS. Поскольку смещение является 16-разрядным, размер сегмента ограничен 64 Кбайтами.

Физический адрес

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

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

     ¦  с м е щ е н и е  ¦

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

+

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

¦  с е л е к т о р  ¦0000¦

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

--------------------------

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

¦    физический адрес    ¦

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

Перенос, который может возникнуть из старшего (19-го) разряда физического адреса в процессе сложения, игнорируется[1]. Таким образом, при доступе к слову памяти, расположенному по смещению 000F16 в сегменте с селектором FFFF16, физический адрес младшего байта этого слова будет равен FFFFF16, а старшего – 0000016.

Легко заметить, что для доступа к одной и той же физической ячейке памяти могут использоваться различные комбинации селекторов и смещений.
Например, физический адрес 0100016 может быть получен при селекторе 000016 и смещении 100016, селекторе 010016 и смещении 000016, а также при множестве других значений селекторов и смещений. Подобный подход к формированию физического адреса оказался весьма неудобным и способствует возникновению трудноуловимых ошибок.

Программист работает с логическими адресами, состоящими из селекторов и смещений. Логический адрес записывается в виде “селектор :

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

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

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

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


Сегментные регистры


Процессор 8086 содержит четыре 16-разрядных сегментных регистра: CS, DS, ES и SS, называемые соответственно сегментными регистрами кода, данных, дополнительных данных и стека.

Процессор использует содержимое сегментных регистров (так называемые селекторы сегментов) для формирования 20-разрядных физических адресов памяти, о чём говорилось выше, в подразделе 2.2.2 “Сегментация”. При обращениях к кодам команд всегда используется сегментный регистр CS, а при обращении к стеку (с использованием указателя стека или при адресации посредством регистра BP) – сегментный регистр SS, причём если адресация данных производится с помощью регистра BP, вместо сегментного регистра SS можно указать любой другой сегментный регистр. При обращении к данным в большинстве случаев по умолчанию используется регистр сегментный регистр DS, однако вместо него в этих ситуациях можно использовать любой другой сегментный регистр. Сегментный регистр ES используется при доступе к строкам-приёмникам в строковых операциях, в этом качестве он не может быть заменён каким-либо другим сегментным регистром.

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

либо извлечено из вершины стека инструкцией POP. Регистр CS не может быть загружен с помощью инструкции MOV

или POP, новое значение в него загружается только при выполнении операций длинных переходов (инструкции JMP, CALL и RET), при возврате из прерывания (инструкция IRET) и при возникновении прерывания. Короткие переходы не изменяют регистр CS. Содержимое всех четырёх сегментных регистров может быть переслано в любой регистр общего назначения инструкцией MOV или занесено в стек инструкцией PUSH.



SHL – логический сдвиг влево


D0 /4

SHL r/m8, 1

логический сдвиг r/m8 влево на 1 разряд

D2 /4

SHL r/m8, CL

логический сдвиг r/m8 влево на CL разрядов

D1 /4

SHL r/m16, 1

логический сдвиг r/m16 влево на 1 разряд

D3 /4

SHL r/m16, CL

логический сдвиг r/m16 влево на CL разрядов

Описание.

Эта инструкция производит логический

(он же арифметический – см. инструкцию SAL) сдвиг содержимого своего операнда влево на указанное вторым операндом число разрядов.

Сдвиг выполняется по следующей схеме:

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

¦CF¦<--+ операнд ¦<- 0

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

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

Флажок CF содержит значение последнего выдвинутого из операнда разряда.

Значение флажка OF в операции многоразрядного сдвига не определено. В операции одноразрядного сдвига он представляет собой результат операции “исключающее ИЛИ” между значением старшего разряда результата и содержимым флажка CF после выполнения сдвига. Таким образом, единичное значение флажка OF свидетельствует о том, что содержимое старшего разряда результата отличается от его исходного значения, а нулевое значение – что старший разряд операнда не изменился.

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

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



SHR – логический сдвиг вправо


D0 /5

SHR r/m8, 1

логический сдвиг r/m8 вправо на 1 разряд

D2 /5

SHR r/m8, CL

логический сдвиг r/m8 вправо на CL разрядов

D1 /5

SHR r/m16, 1

логический сдвиг r/m16 вправо на 1 разряд

D3 /5

SHR r/m16, CL

логический сдвиг r/m16 вправо на CL разрядов

Описание.

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

Сдвиг выполняется по следующей схеме:

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

0 ->¦ операнд +-->¦CF¦

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

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

Флажок CF содержит значение последнего выдвинутого из операнда разряда.

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

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



Символьная информация


Символьная информация хранится в памяти вычислительной машины. Набор строковых операций позволяет одной командой обработать один или два байта памяти, а также организовать повторение строковых команд. Максимальное число повторений – 65536. Из-за особенностей адресации (использования 16-разрядных сегментного адреса и смещения) максимальный размер строки ограничен 65536 символами, хотя счётчик повторений при использовании операций, работающих со словами, позволяет обработать вдвое больший объём данных.

Строковые операции могут выполняться как слева направо (в сторону увеличения адресов), так и справа налево (в сторону уменьшения адресов).



Система команд


Микропроцессор 8086 насчитывает 135 различных команд. В этой главе описываются все инструкции и префиксы, используемые микропроцессором, и указываются возможные форматы этих команд. Инструкции математического сопроцессора, “дополняющие” команду ESC микропроцессора 8086, не рассматриваются, поскольку они не относятся к системе команд микропроцессора 8086 и реализуются сопроцессором 8087 (КР1810ВМ87).



STC – установка флага переноса


F9

STC

CF:= 1

Описание.

Устанавливается флажок переноса CF регистра FLAGS.

Флажок CF устанавливается, остальные флажки не изменяются.



STD – установка флага направления


FD

STD

DF:= 1

Описание.

Устанавливается флажок переноса DF регистра FLAGS.

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

Флажок CF устанавливается, остальные флажки не изменяются.



Стек


Микропроцессор 8086 поддерживает аппаратный стек. Регистровая пара SS:SP (селектор сегмента находится в регистре SS, а смещение – в регистре SP) указывает на слово, являющееся вершиной стека. Регистр SP должен содержать чётное значение, т.е. стек всегда должен быть выровнен на границу слова. При записи или чтении байта в стек будет помещено или из стека будет извлечено слово (два байта).

Стек микропроцессора 8086 растёт вниз. Это означает, что при записи слова в стек содержимое регистра SP уменьшается на два, после чего производится запись в стек по адресу SS:SP. При извлечении данных из стека сначала считывается слово по адресу SS:SP, а затем содержимое SP увеличивается на два. Если операция выполнялась над байтом, то этот байт будет младшим байтом слова, записываемого или извлекаемого из стека. Значение старшего байта при записи предсказать невозможно; при чтении из стека его значение игнорируется.

Запись в стек имеет место в следующих случаях:

– при выполнении инструкции PUSH, записывающей в стек значение своего операнда;

– при выполнении инструкции PUSHF, записывающей в стек содержимое регистра флагов;

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

– при выполнении прерывания (в стек записывается три слова – содержимое регистра флагов и адрес возврата из прерывания).

Чтение из стека происходит:

– при выполнении инструкций POP

и POPF, обратных инструкциям PUSH и PUSHF;

– при выполнении инструкции RET, обеспечивающей возврат из подпрограммы (извлекается одно или два слова в зависимости от того, какой возврат – ближний или дальний – выполняется);

– при выполнении инструкции возврата из прерывания IRET (извлекается три слова – дальний адрес возврата из подпрограммы и содержимое слова флагов).

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



STI – установка флага разрешения прерывания


FB

STI

IF:= 1

Описание.

Устанавливается флажок переноса IF регистра FLAGS.

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

Флажок IF устанавливается, остальные флажки не изменяются.



STOS – запись строки


AA

STOSB

запись байта из AL в [ES:DI]

AB

STOSW

запись слова из AX в [ES:DI]

Описание.

Эта инструкция записывает содержимое регистра AL или AX по адресу ES:DI.

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

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

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



SUB – двоичное вычитание


28 /r

SUB r/m8, r8

r/m8:= r/m8 – r8

29 /r

SUB r/m16, r16

r/m16:= r/m16

– r16

2A /r

SUB r8, r/m8

r8:= r8

– r/m8

2B /r

SUB r16, r/m16

r16:= r16 –

r/m16

2C ib

SUB AL, imm8

AL:= AL – imm8

2D iw

SUB AX, imm16

AX:= AX – imm16

80 /5 ib

SUB r/m8, imm8

r/m8:= r/m8

– imm8

81 /5 iw

SUB r/m16, imm16

r/m16:= r/m16

– imm16

83 /5 ib

SUB r/m16, imm8

r/m16:= r/m16 – imm8

Описание.

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

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

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



Таблица векторов прерываний


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

Таблица векторов прерываний занимает младший 1 Кбайт физического адресного пространства микропроцессора. Каждому вектору в ней соответствует четырёхбайтовая область. Первое слово любого вектора прерывания содержит смещение, а второе слово – селектор сегмента обработчика прерывания, назначенного этому вектору. Таким образом, каждый вектор является дальним адресом (парой “сегмент : смещение”) соответствующего обработчика прерывания.



TEST – логическое сравнение


84 /r

TEST r/m8, r8

r/m8 AND r8

85 /r

TEST r/m16, r16

r/m16 AND r16

A8 ib

TEST AL, imm8

AL AND imm8

A9 iw

TEST AX, imm16

AX AND imm16

F6 /0 ib

TEST r/m8, imm8

r/m8 AND imm8

F7 /0 iw

TEST r/m16, imm16

r/m16 AND imm16

Описание.

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

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

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

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

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



Указатель инструкции


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

Регистр IP не может напрямую использоваться в арифметико-логических командах. Его содержимое сохраняется в стеке при обращении к подпрограмме с помощью инструкции CALL, а также при возникновении прерывания. Восстановление содержимого регистра IP из стека возможно только с помощью инструкций возврата из прерывания IRET

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



Внешние прерывания


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



Выполнение инструкций


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

– инструкции пересылки;

– арифметико-логические инструкции;

–­ инструкции сдвигов;

– инструкции обработки строк;

– инструкции переходов;

– инструкции управления и вспомогательные;

– префиксы инструкций.

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

Выполнение каждой инструкции складывается из следующих шагов:

– выборки из памяти и дешифровки кода команды;

– определения местоположения операндов, если они явно задаются кодом команды (некоторые инструкции не имеют операндов вообще, в некоторых других местоположение операндов подразумевается);

– вычисления эффективного адреса операнда в памяти, если таковой имеется;

– собственно выполнения инструкции.



WAIT – ожидание сопроцессора


9B

WAIT

переход в ожидание готовности сопроцессора

Описание.

Эта инструкция приостанавливает дальнейшее выполнение программы до поступления сигнала готовности от сопроцессора.

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

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



XCHG – обмен информацией


90+rw

XCHG AX, r16

AX - r16

90+rw

XCHG r16, AX

r16 - AX

86 /r

XCHG r/m8, r8

r/m8 - r8

86 /r

XCHG r8, r/m8

r8 - r/m8

87 /r

XCHG r/m16, r16

r/m16 - r16

87 /r

XCHG r16, r/m16

r16 - r/m16

Описание.

Эта инструкция меняет местами содержимое своих операндов.

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



XLATB – табличная перекодировка


D7

XLATB

AL:= [BX+AL]

Описание.

Эта инструкция перекодирует по таблице значение регистра AL.

Начальный адрес 256-байтовой таблицы перекодировки содержится в регистре BX. Перекодировка заключается в том, что из ячейки таблицы, номер которой содержится в регистре AL, извлекается байт и заносится в регистр AL.

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



XOR – исключающее ИЛИ


30 /r

XOR r/m8, r8

r/m8:= r/m8

XOR r8

31 /r

XOR r/m16, r16

r/m16:= r/m16 XOR r16

32 /r

XOR r8, r/m8

r8:= r8 XOR r/m8

33 /r

XOR r16, r/m16

r16:= r16 XOR r/m16

34 ib

XOR AL, imm8

AL:= AL XOR imm8

35 iw

XOR AX, imm16

AX:= AX XOR imm16

80 /6 ib

XOR r/m8, imm8

r/m8:= r/m8 XOR imm8

81 /6 iw

XOR r/m16, imm16

r/m16:= r/m16 XOR imm16

Описание.

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

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

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

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



при выполнении операции сложения распакованных


Инструкция AAA используется совместно с инструкцией ADD
или ADC
при выполнении операции сложения распакованных двоично-десятичных чисел. Сложение выполняется последовательно – по одному десятичному разряду. Складываемые двоично-десятичные значения перед выполнением команды сложения располагаются в младших полубайтах её операндов, причём один из них – в младшем полубайте регистра AL. Следующая за инструкцией сложения команда коррекции на основании полученного результата и состояния флажка вспомогательного переноса корректирует результат в регистре AL. Флажок CF, установленный после выполнения инструкции AAA, свидетельствует о том, что возник перенос в следующий разряд распакованного двоично-десятичного числа, который должен быть учтён при выполнении следующего прохода сложения.


Инструкция AAD предшествует инструкции DIV
и корректирует делимое, состоящее из двух двоично-десятичных цифр, находящихся в младших полубайтах регистров AH и AL; старшие полубайты при этом должны быть равны нулю. Делитель должен быть двоично-десятичным одноразрядным распакованным числом, т.е. иметь значение от 0 до 9. В результате выполнения команды DIV в регистре AL будет сформировано правильное двоичное частное. Для его преобразования в двоично-десятичный можно воспользоваться инструкцией AAM. Остаток принимает значение 0–9 в зависимости от значения исходных операндов, поэтому не нуждается в дополнительном преобразовании в двоично-десятичный вид.
Фирменные руководства ничего не говорят о том, используются ли при выполнении инструкции AAD значения старших полубайтов регистров AH и AL, поэтому лучше перестраховаться и обеспечить их обнуление.
Инструкция AAD может использоваться для преобразования двухразрядного десятичного числа в двоичное.


Инструкция AAM может использоваться для преобразования двоичного числа без знака в двухразрядное десятичное.


Совместно с командами десятичной коррекции сложения AAA
и DAA
инструкция ADD
обеспечивает сложение двоично-десятичных распакованных и упакованных чисел.
Если необходимо складывать числа с разрядностью, превышающей 16, младшие 16 бит складываются инструкцией ADD, а все последующие – инструкцией ADC.


Команда ADC используется при сложении двоичных чисел с разрядностью, превышающей 16. В этом случае сложение младших частей операндов выполняется с помощью инструкции ADD, а последующих частей операндов – с помощью инструкций ADC, следующих за ADD.
Совместно с командами десятичной коррекции сложения AAA
и DAA
инструкции ADD
и ADC
обеспечивают сложение двоично-десятичных распакованных и упакованных чисел.


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


Декремент 16- разрядных регистров общего назначения может быть выполнен двумя видами инструкций – однобайтовой (код операции 48 плюс номер регистра) и двухбайтовой (код операции FF, номер регистра определяется байтом ModRegR/M). Транслятор языка ассемблера автоматически генерирует однобайтовый код операции как более компактный; второй вариант при необходимости может быть запрограммирован вручную.


Хотя аппаратная архитектура микропроцессора 8086/8088 позволяла подключить к нему сопроцессор произвольного назначения, был разработан и получил распространение только арифметический сопроцессор 8087. Описание его системы команд не входит в задачу данной публикации.


Инкремент 16- разрядных регистров общего назначения может быть выполнен двумя видами инструкций – однобайтовой (код операции 40 плюс номер регистра) и двухбайтовой (код операции FF, номер регистра определяется байтом ModRegR/M). Транслятор языка ассемблера автоматически генерирует однобайтовый код операции как более компактный; второй вариант при необходимости может быть запрограммирован вручную.


Прерывание по вектору 3 (отладочное) может быть выработано инструкциями двух видов – специальной однобайтовой с кодом CC и общей двухбайтовой CD 03. Трансляторы с языка ассемблера для инструкции INT 3 всегда генерируют код CC; двухбайтовый код CD 03 может быть при необходимости сформирован вручную.
Однобайтовый код операции интенсивно используется отладчиками для формирования точек останова, поскольку позволяет заменить код операции любой команды, в том числе и однобайтовой.


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


Многие инструкции условных переходов имеют по несколько мнемоник для одного и того же кода операций. Та или иная мнемоника позволяет точнее указать, какой именно тип анализа с точки зрения человека выполняется командой перехода в данном месте программы, хотя функционально команды с разными мнемониками, на одинаковыми кодами операций абсолютно равнозначны. Например, мнемоника JZ
может быть применена, когда предыдущая инструкция проверяла содержимое какой-либо ячейки памяти на нуль, в то время как мнемоника JE, соответствующая той же самой машинной операции (код операции 74), применяется после инструкции сравнения двух величин. В том и другом случае переход произойдёт, если установлен флажок ZF.
Инструкции, в названии которых содержатся слова “больше” или “меньше”, предназначены для анализа результатов сравнения чисел со знаком, а инструкции, содержащие слова “выше” и “ниже”, предназначены для анализа результатов сравнения беззнаковых чисел. В командах, предназначенных для переходов по результатам сравнения чисел со знаком, анализируются флажки SF и OF, а в командах для беззнаковых сравнений – флажок CF. Равенство или неравенство чисел независимо от наличия у них знака в любом случае отражается состоянием флажка ZF.
Инструкция JCXZ является единственной командой условного перехода, которая не проверяет состояние какого-либо флажка или группы флажков. Вместо этого она проверяет содержимое регистра CX. Поскольку этот регистр используется в качестве счётчика при выполнении строковых операций, инструкция JCXZ дополняет набор префиксов повторения, специально предназначенных для работы совместно с операциями обработки строк. Кроме того, эта команда может использоваться для организации циклов при использовании регистра CX в качестве счётчика итераций вместо инструкции LOOP, когда значение счётчика не уменьшается на 1 при каждом проходе цикла, как то предусмотрено последней командой.


В том случае, когда эффективный адрес однозначно определяется отклонением, вместо команды LEA выгоднее использовать команду MOV с кодом операции B8–BF. Команда MOV
займёт 3 байта памяти вместо 4 и на процессоре 8086 будет выполняться в два раза быстрее (4 такта вместо 8).


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


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


Строго говоря, инструкция NOP является инструкцией XCHG AX, AX.


Выполнение инструкции POP SP
приведёт к загрузке в SP слова из старой вершины стека, поскольку увеличение SP на 2 производится после выборки слова из вершины стека, но до занесения этого слова в операнд инструкции.


Выполнение инструкции PUSH SP
приведёт к записи в стек нового содержимого SP, т.е. значения, которое находится в этом регистре после вычитания. В процессоре 80286 и последующих в стек заносится исходное содержимое регистра SP, т.е. его значение до вычитания.


Микропроцессоры 8086 и 8088 не маскируют значение счётчика сдвига. Таким образом, сдвиг может быть выполнен на произвольное число разрядов от 0 до 255. В процессорах, начиная с 80286, в качестве счётчика сдвига используются только младшие 5 разрядов регистра CL, что ограничивает максимальное количество сдвигов (не более 31).


Микропроцессоры 8086 и 8088 не маскируют значение счётчика сдвига. Таким образом, сдвиг может быть выполнен на произвольное число разрядов от 0 до 255. В процессорах, начиная с 80286, в качестве счётчика сдвига используются только младшие 5 разрядов регистра CL, что ограничивает максимальное количество сдвигов (не более 31).


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


Микропроцессоры 8086 и 8088 не маскируют значение счётчика сдвига. Таким образом, сдвиг может быть выполнен на произвольное число разрядов от 0 до 255. В процессорах, начиная с 80286, в качестве счётчика сдвига используются только младшие 5 разрядов регистра CL, что ограничивает максимальное количество сдвигов (не более 31).


Микропроцессоры 8086 и 8088 не маскируют значение счётчика сдвига. Таким образом, сдвиг может быть выполнен на произвольное число разрядов от 0 до 255. В процессорах, начиная с 80286, в качестве счётчика сдвига используются только младшие 5 разрядов регистра CL, что ограничивает максимальное количество сдвигов (не более 31).


Микропроцессоры 8086 и 8088 не маскируют значение счётчика сдвига. Таким образом, сдвиг может быть выполнен на произвольное число разрядов от 0 до 255. В процессорах, начиная с 80286, в качестве счётчика сдвига используются только младшие 5 разрядов регистра CL, что ограничивает максимальное количество сдвигов (не более 31).


Микропроцессоры 8086 и 8088 не маскируют значение счётчика сдвига. Таким образом, сдвиг может быть выполнен на произвольное число разрядов от 0 до 255. В процессорах, начиная с 80286, в качестве счётчика сдвига используются только младшие 5 разрядов регистра CL, что ограничивает максимальное количество сдвигов (не более 31).


Команда SBB используется при вычитании двоичных чисел с разрядностью, превышающей 16. В этом случае вычитание младших частей операндов выполняется с помощью инструкции SUB, а последующих частей операндов – с помощью инструкций SBB, следующих за SUB.
Совместно с командами десятичной коррекции сложения AAS
и DAS
инструкции SUB
и SBB
обеспечивают вычитание двоично-десятичных распакованных и упакованных чисел.


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


Микропроцессоры 8086 и 8088 не маскируют значение счётчика сдвига. Таким образом, сдвиг может быть выполнен на произвольное число разрядов от 0 до 255. В процессорах, начиная с 80286, в качестве счётчика сдвига используются только младшие 5 разрядов регистра CL, что ограничивает максимальное количество сдвигов (не более 31).


Микропроцессоры 8086 и 8088 не маскируют значение счётчика сдвига. Таким образом, сдвиг может быть выполнен на произвольное число разрядов от 0 до 255. В процессорах, начиная с 80286, в качестве счётчика сдвига используются только младшие 5 разрядов регистра CL, что ограничивает максимальное количество сдвигов (не более 31).


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


Команда SUB используется при вычитании двоичных чисел с разрядностью 8 или 16. Если требуется выполнить вычитание более длинных чисел, младшие их части вычитаются с помощью инструкции SUB, а остальные – с помощью инструкции SBB.
Совместно с командами десятичной коррекции сложения AAS
и DAS
инструкции SUB
и SBB
обеспечивают вычитание двоично-десятичных распакованных и упакованных чисел.


Архитектура микропроцессоров 8086/8088 позволяет подключить к ним сопроцессор любого назначения, выполняющий те или иные дополнительные команды и, естественно, согласующий свою работу на уровне аппаратуры с основным процессором. Коды этих команд содержат в старших пяти разрядах первого байта комбинацию 11011; для основного процессора это команда ESC. Исторически сложилось, что единственным используемым сопроцессором стал арифметический сопроцессор 8087, содержащий мощную собственную систему команд. Её описание не входит в задачу данной публикации.