Пояснения к основным таблицам

**Таблица. Источник:** Справочник по командам процессоров x86

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

### Примеры из разных таблиц

Здесь выбраны несколько типичных строчек из разных таблиц, чтобы на этих примерах продемонстрировать применяемые в таблицах обозначения.

### Предварительные замечания

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

Команды ассемблера и машинные командыНа этой же странице есть дополнительные объяснения про термин "основной байт кода операции", такой термин часто используется в данном справочние.
Кроме того, полезно ознакомиться со страницей

Структура машинной команды===Колонки в основных таблицах===
Колонка **Код** содержит код операции машинной команды. Код операции состоит из одного байта или из двух байт и показан в таблицах в виде одного или двух шестнадцатеричных чисел.

Иногда к коду операции могут добавляться три дополнительных бита. Об этом подробно рассказано ниже - см. "Обозначение NNN".

Колонка **Команда** содержит имя команды на языке ассемблера. Иногда рядом добавляется имя регистра, так бывает, если регистр задается (в качестве операнда) прямо в коде операции.

Колонка **Формат** показывает формат машинной команды. Используемые при этом условные обозначения объясняются ниже. Следует особо подчеркнуть, что формат относится к машинной команде, а не к команде на языке ассемблера.

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

### Формат машинной команды

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

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

Первым в формате всегда идет "основной байт кода операции".

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

В колонке "Формат" основной байт кода операции показан в виде условных восьми черточек, на которых отмечены особые биты, если таковые есть в основном байте кода операции данной машинной команды.

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

### Особые биты и битовые поля в основном байте

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

Возможны следующие биты и битовые поля.

Бит **( w )** в основном байте кода операции ("word" - "слово") определяет размер операнда. Если ( w = 0 ), то операция выполняется для одного байта (размер операнда 8 бит). Если ( w = 1 ), то операция выполняется для слова (два байта) или для двойного слова (четыре байта), соответственно размер операнда будет 16 бит или 32 бита (в зависимости от установленного для этой команды атрибута размера операнда). Бит ( w ) обычно находится в нулевом (самом младшем) разряде основного байта. Но есть одна группа машинных команд (команда MOV, коды B0 - BF), в которых бит ( w ) помещен в третий разряд (при счете от нуля) основного байта.

Бит **( d )** в основном байте кода операции ("direction" - "направление") определяет порядок операндов. Такой бит возможен только в командах, содержащих байт ( mod,reg,r/m ). Если ( d=0 ), то операнд ( reg )является источником (source), а операнд ( r/m ) приемником (destination). Если ( d=1 ), то наоборот, ( reg ) является приемником (destination), а ( r/m ) - источником (source). Бит ( d ) всегда находится в первом разряде (при счете от нуля) основного байта.

Бит **( s )** в основном байте кода операции ("sign" - "знак") определяет наличие знакового расширения. Такой бит возможен для команд с непосредственным операндом. Если ( s=1 ), то непосредственный операнд занимает в команде только один байт и расширяется (со знаком) до размера, задаваемого аттрибутом размера операнда данной команды (16 бит или 32 бита). Бит ( s ) всегда находится в первом разряде (при счете от нуля) основного байта.

Примечание. Не путайте бит ( s ) с полем из двух битов ( sr ) или из трех битов ( sgr ).

Поле **( reg )**, состоящее из трех бит ("register" - "регистр") содержит код регистра общего назначения, с которым работает данная команда. Иначе говоря, три бита из основного байта кода операции выделены на задание операнда - регистра. Кодирование для поля ( reg ) смотрите на странице  Регистры общего назначения.

Поле **( sr )**, состоящее из двух бит, или поле **( sgr )** из трех бит ("segment register") определяет сегментный регистр, с которым работает данная команда. Регистры ES, CS, SS, DS могут быть заданы в двухбитном поле ( sr ) или в трехбитном поле ( sgr ). Регистры FS и GS могут задаваться только в трехбитном поле ( sgr ). Коды задания сегментных регистров смотрите на странице  Коды сегментных регистров.

Поле **( cond )**, состоящее из четырех бит ("condition" - "условие"), определяет условие, по которому работает условная команда (например, команда условной передачи управления). Условие - это определенное состояние флажков. Подробности смотрите на странице  Условные команды.

Поле **( fpu )**, состоящее из трех бит ("floating-point unit"), присутствует в первом байте команд сопроцессора с плавающей точкой. Код операции для сопроцессора состоит из шести бит. Старшие три бита находятся в поле ( fpu ) первого байта, младшие в поле ( reg ) байта ( mod,reg,r/m ). См. ниже про обозначение ( NNN ).

Примечание. Для ранних процессоров x86 сопроцессор с плавающей точкой был отдельным устройством. Начиная с i486, сопроцессор входит в состав основного процессора.

### Дополнительные байты в машинной команде

Если в данной машинной команде после кода операции нет других байтов, то в таблице в колонке "Формат" будет показан только основной байт кода операции (условно, в виде черточек).

Если в команде после основного байта есть еще и дополнительные байты, то они будут обозначены в колонке "Формат" следующим образом.

#### Обозначение MRM

Обозначение **MRM** означает, что после байта с кодом операции идет далее байт режима адресации - байт MRM ( mod,reg,r/m ), после которого может следовать второй байт режима адресации - байт SIB( scale,index,base ), а затем еще и байты смещения. Смещение может состоять из одного, двух или четырех байтов. Подробности смотрите на странице  Структура машинной команды.

Если в формате машинной команды присутствует обозначение MRM, то при записи этой команды на языке ассемблера байту ( mod,reg,r/m ) соответствуют два операнда. Один из этих операндов соответствует полю ( reg ) и задает регистр, а второй операнд соответствует полю ( r/m ) и задает либо регистр, либо адрес в памяти. Порядок следования этих двух операндов может оказаться разным для разных конкретных команд.

В колонке "Формат" ставится только обозначение MRM и не показываются другие байты (второй байт режима адресации и байты смещения), связанные с байтом MRM. То же самое односится и к обозначению NNN, о котором рассказано ниже.

#### Обозначение NNN

Обозначение **NNN** тоже означает, что после байта с кодом операции идет далее байт MRM ( mod,reg,r/m ) и все последующие байты, к нему относящиеся. Таким образом, если в команде присутствует байт MRM, то в таблицах справочника в колонке "Формат" это будет показано либо обозначением MRM, либо обозначением NNN.

В отличие от случая, обозначенного как ( MRM ), в случае ( NNN ) трехбитное поле ( reg ) в байте ( mod,reg,r/m ) не задает регистр. Эти три бита поля ( reg ) присоединяются к коду операции и тогда уже этот удлиненный код операции будет определять, какая команда должна выполняться. Таким образом, если в формате команды присутствует ( NNN ), то с данным значением основного байта кода операции получается уже не одна машинная команда, а целая группа из восьми разных машинных команд. (Три дополнительных бита могут иметь восемь разных значений).

Если в формате машинной команды присутствует обозначение NNN, то при записи этой команды на языке ассемблера байту ( mod,reg,r/m ) соответствует только один операнд. Этот операнд соответствует полю ( r/m ) и задает либо регистр, либо адрес в памяти.

Если для некоторой команды в таблице, в колонке "Формат" стоит обозначение NNN, то в той же строке таблицы в колонке "Код" (или в колонке "Команда") будет показано значение поля ( reg ) байта ( mod,reg,r/m ), которое должно быть для этой команды. Это значение дается в двоичном виде после дробной черты, например, ( /010 ).

Имеется несколько случаев, когда значение поля ( reg ) байта ( mod,reg,r/m ) никак не используется и должно быть всегда равно нулю. Таких случаев совсем немного:

* команда MOV, коды C6 и C7
* команда POP, код 8F
* группа команд SET(cond), коды от 0F 90 до 0F 9F

Для этих случаев в колонке формат тоже ставится обозначение NNN. Однако, чтобы не загромождать таблицы, значение ( reg ), равное ( /000 ), показано не везде. На языке ассемблера в этих случаях байту ( mod,reg,r/m ) все также соответствует только один операнд (регистр или память), о чем и свидетельствует обозначение NNN.

#### Обозначение addr(...)

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

После слова ( addr ) в скобках указывается количество байт. Если количество байт может быть разным (для разных режимов работы 16/32 бит), то указываются два числа через дробь, например: addr(2/4).

Обозначение addr(...) встречается, прежде всего, в командах передачи управления. И есть только одна команда, в которой так задается полный адрес в оперативной памяти для чтения и записи данных, это команда MOV с кодами A0 - A3.

#### Обозначение data(...)

Обозначение **data(...)** означает, что в состав команды входит непосредственный операнд. В скобках указан размер операнда - количество байт. Если указано несколько чисел (через дробь), то размер операнда может быть разным - например: data(1/2/4).

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

На языке ассемблера обозначению data(...) соотвествует один операнд.