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

Печать
Программирование - Архитектура и система команд микропроцессоров x86

 

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

 

Мнемоника

Название команды

Влияние команды на флаги и форматы команды:

OF

DF

IF

TF

SF

ZF

AF

PF

CF

Влияние на флаги: * ? 0 1



Код

Команда

Описание

Процессор

Пример

Информация о коде и действии команды, процессор, где эта команда была введена впервые, а также пример мнемоники команды

 

После таких таблиц следуют пункты:

  • "Операция:",
  • "Описание:",
  • "Особые ситуации защищенного режима:",
  • "Особые ситуации режима реальной адресации:",
  • "Особые ситуации режима V86:"
  • и иногда ,"Замечание:".

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

 

Влияние команды на флаги и форматы команды:

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

*         – флаг устанавливается по результатам операции;

пусто  – флаг не изменяется;

?         – флаг принимает неопределенное значение;

0         – флаг сбрасывается;

1         – флаг устанавливается.

Для команд FPU таблица влияния на флаги содержит информацию о влиянии команды на флаги в регистре состояния FPU (SW), а для команд SIMD в регистре статуса SIMD (MXCSR). Поскольку команды MMX и 3DNow! не оказывают влияния на флаги в регистрах состояния процессора или сопроцессора, то для этих команд таблица влияния на флаги всегда пуста.

 

Колонка кода операции ("Код")

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

/цифра
Цифра (от 0 до 7 включительно) сигнализирует, что ModR/M байт команды использует только r/m-операнд (регистр или память). Поле reg содержит цифру, используемую для расширения кода операции.

/r
Сигнализирует о том, что ModR/M байт содержит и регистровый операнд, и r/m-операнд.

cb, cw, cd, cp
Однобайтная (cb), двухбайтная (cw), четырехбайтная (cd) или шестибайтная (cp) величина, следующая за кодом операции и определяющая значение смещения в кодовом сегменте или новое значение для регистра кодового сегмента.

ib, iw, id
Однобайтный (ib), двухбайтный (iw) или четырехбайтный (id) непосредственный операнд, следующий за кодом операции, ModR/M байтом или SIB байтом. Код операции определяет, является ли операнд знаковой величиной. Все двухбайтные (word) и четырехбайтные (dword) значения приводятся начиная с младшего байта.

+rb, +rw, +rd
Код регистра (от 0 до 7), прибавляемый к байту, приведенному слева от знака плюс, для образования однобайтного кода. В таблице 6.2. приведены значения кодов.

Таблица 6.2. Коды регистров


rb

rw

rd

AL = 0

AX = 0

EAX = 0

CL = 1

CX = 1

ECX = 1

DL = 2

DX = 2

EDX = 2

BL = 3

BX = 3

EBX = 3

AH = 4

SP = 4

ESP = 4

CH = 5

BP = 5

EBP = 5

DH = 6

SI = 6

ESI = 6

BH = 7

DI = 7

EDI = 7

 

+i
Используется в командах FPU, когда один из операндов — регистр стека сопроцессора ST(i). Число i (от 0 до 7) прибавляется к байту, приведенному слева от знака плюс, для получения однобайтного кода.

При описании команд 3DNow! значения в поле код операции представлены в виде:

код команды / суффикс 3DNow!

Именно суффикс, который следует за ModR/M и SIB байтами однозначно идентифицирует конкретную 3DNow!-команду. Для более полной информации по этому вопросу обратитесь к описанию формата команд 3DNow! 

 

Колонка команды ("Команда")

В колонке команды приводится синтаксическое выражение команды (мнемокод). При представлении операндов в мнемокоде команды используются следующие обозначения:

rel8
Относительный адрес в диапазоне от -128 байт до +127 байт от конца команды.

rel16, rel32
Относительный адрес внутри того же кодового сегмента, в котором команда ассемблируется. rel16 применима к командам с атрибутом 16-битного размера операнда, rel32 применима к командам с атрибутом 32-битного размера операнда.

ptr16:16, ptr16:32
Дальний указатель (обычно в кодовый сегмент, отличный от кодового сегмента команды). Употребление ptr16:16 сигнализирует о том, что значение указателя состоит из двух частей. Значение, приведенное слева от двоеточия, это 16-битный селектор или значение для регистра кодового сегмента. Значение справа от двоеточия соответствует смещению в сегменте назначения. ptr16:16 используется в командах с атрибутом 16-битного размера операнда. ptr16:32 используется в командах с атрибутом 32-битного размера операнда.

r8
Один из однобайтных регистров AL, CL, DL, BL, AH, CH, DH или BH.

r16
Один из двухбайтных регистров AX, CX, DX, BX, SP, BP, SI или DI.

r32
Один из четырехбайтных регистров EAX, ECX, EDX, EBX, ESP, EBP, ESI или EDI.

Sreg
Сегментный регистр. В коде операции биты идентификации сегментного регистра определены следующим образом: ES = 0, CS = 1, SS = 2, DS = 3, FS = 4, GS = 5.

ST или ST(0)
Верхний элемент регистрового стека FPU.

ST(i)
i-ый элемент от вершины регистрового стека FPU.

mm
Регистр MMX. Существует восемь 64-битных MMX-регистров: MM0, … MM7.

xmm
Регистр SIMD. Существует восемь 128-битных SIMD-регистров: XMM0, … XMM7.

r/m8
Однобайтный операнд, который представляет собой содержимое байтового регистра (AL, CL, DL, BL, AH, CH, DH или BH) или байта памяти, и для адресации которого допустимы все режимы, поддерживаемые в коде команды байтами ModR/M и SIB.

r/m16
Двухбайтный операнд, используемый в командах с атрибутом 16-битного размера операнда, который представляет собой содержимое двухбайтного регистра (AX, CX, DX, BX, SP, BP, SI, DI) или слова памяти, и для адресации которого допустимы все режимы адресации, поддерживаемые в коде команды байтами ModR/M и SIB.

r/m32
Четырехбайтный операнд, используемый в командах с атрибутом 32-битного размера операнда, который представляет собой содержимое четырехбайтного регистра (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI) или двойного слова памяти, и для адресации которого допустимы все режимы адресации, поддерживаемые в коде команды байтами ModR/M и SIB.

mm/m32
Регистр MMX или 32-битный операнд в памяти, используемый в командах MMX. Регистры MMX: MM0, … MM7. Для операнда в памяти допустимы любые режимы адресации.

mm/m64
Регистр MMX или 64-битный операнд в памяти, используемый в командах MMX. Регистры MMX: MM0, … MM7. Для операнда в памяти допустимы любые режимы адресации.

xmm/m64
Регистр SIMD или 64-битный операнд в памяти, используемый в командах SIMD. Регистры SIMD: XMM0, … XMM7. Для операнда в памяти допустимы любые режимы адресации.

xmm/m128
Регистр SIMD или 128-битный операнд в памяти, используемый в командах SIMD. Регистры SIMD: XMM0, … XMM7. Для операнда в памяти допустимы любые режимы адресации.

imm8
Непосредственная однобайтная величина imm8 — это однобайтовое знаковое целое значение, число от -128 до +127 включительно. При выполнении разных команд целочисленной арифметики (ADD, ADC, SUB, SBB, IMUL, MUL, IDIV, DIV, CMP), в которых imm8 используется совместно с двухбайтным или четырехбайтным операндом, такая непосредственная величина перед выполнением заданной арифметической операции знакорасширяется до размера второго операнда — слова или двойного слова (при этом старшие биты слова или двойного слова заполняются старшим битом исходной непосредственной величины).

imm16
Непосредственная двухбайтная величина imm16 — это двухбайтовое знаковое целое значение, число от -32768 до +32767 включительно, используемое при 16-битном размере операнда. При выполнении разных команд целочисленной арифметики (ADD, ADC, SUB, SBB, IMUL, MUL, IDIV, DIV, CMP), в которых imm16 используется совместно с четырехбайтным операндом, такая непосредственная величина перед выполнением заданной арифметической операции знакорасширяется до двойного слова (старшее слово заполняется старшим битом исходной непосредственной величины).

imm32
Непосредственная четырехбайтная величина imm32 — это четырехбайтовое знаковое целое значение, число от -2147483648 до +2147483647 включительно, используемое при 32-битном размере операнда при выполнении разных команд целочисленной арифметики (ADD, ADC, SUB, SBB, IMUL, MUL, IDIV, DIV, CMP).

m
16- или 32-битный операнд в памяти.

m8
Байт памяти, адресуемый DS:(E)SI или ES:(E)DI (используется только строковыми командами).

m16
Слово памяти адресуемое DS:(E)SI или ES:(E)DI (используется только строковыми командами).

m32
Двойное слово памяти адресуемое DS:(E)SI или ES:(E)DI (используется только строковыми командами).

m64
Учетверенное слово в памяти. Такой операнд используется только в команде CMPXCHG8B.

m128
Двойное учетверенное слово в памяти. Используется только в SIMD-командах.

m16int, m32int, m64int
Целочисленные операнды FPU в памяти (cоответственно: целое слово, короткое целое, длинное целое).

m32real, m64real, m80real
Вещественные операнды FPU в памяти (соответственно: короткое вещественное, длинное вещественное, временное вещественное).

m80dec
Двоично-десятичный операнд FPU в памяти.

mNbyte
N-байтный операнд FPU в памяти.

m16:16, m16:32
Операнд в памяти, содержащий дальний указатель, состоящий из двух чисел. Число слева от двоеточия соответствует селектору сегмента указателя, число справа соответствует его смещению. Для команд с такими операндами разрешены все режимы адресации.

m16&32, m16&16, m32&32
Операнд в памяти, состоящий из пар элементов данных, размеры которых указаны слева и справа от знака амперсанда. Для команд с такими операндами разрешены все режимы адресации. m16&16 и m32&32 используются в команде BOUND для хранения верхней и нижней границ индексов массива. m16&32 используется командами LIDT и LGDT для обеспечения загрузки значения поля предела (из слова) и значения поля базы (из двойного слова) регистров глобальной таблицы дескрипторов и таблицы дескрипторов прерываний (GDTR и IDTR).

moffs8, moffs16, moffs32
Простая переменная в памяти типа BYTE, WORD или DWORD, используемая некоторыми вариантами команды MOV. Фактический адрес этой переменной задается при помощи простого смещения относительно базы сегмента. Поскольку смещение задается непосредственно, ModR/M байт в такой команде не используется. Число, указанное в moffs, указывает разрядность переменной, которая определяется атрибутом размера адреса команды и кодом операции.

 

Колонка описания ("Описание")

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

 

Колонка процессора ("Проц.")

Эта колонка содержит наименование микропроцессора, в котором описываемая команда (модификация команды) была введена впервые. Следует иметь ввиду, что некоторые команды (например, CPUID), которые вводились в новых моделях процессоров, впоследствии реализовывались и в новых модификациях старых процессоров. В подобных случаях колонка процессора может отсутствовать в описании формата команды.

 

Колонка примеров ("Пример")

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

 

Описание:

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

 

Операция:

Пункт "Операция" содержит алгоритм выполнения команды на языке подобном ALGOL или PASCAL. В алгоритмах используются следующие конструкции:

  • комментарии выделяются парами символов "(*" и "*)";
  • составные выражения заключаются между ключевыми словами "if" (выражение IF, THEN, ELSE, FI), "do" (выражение DO, OD) или "case" (выражение CASE...OF, ESAC);
  • операция продолжается до тех пор, пока не встретится ключевое слово END;
  • под именем регистра подразумевается его содержимое;
  • имя регистра, любого операнда или переменной, заключенное в скобки, подразумевает содержимое ячейки памяти, адрес которой содержится в этом регистре, операнде или переменной, например, ES:[DI] указывает на содержимое ячейки памяти сегмента ES с относительным адресом в регистре DI. [SI] указывает на содержимое ячейки памяти по адресу содержащемуся в регистре SI относительно его сегмента по умолчанию (сегмента DS) или замещающего сегмента;
  • A = B указывает, что величине A присваивается значение B;
  • символы =, , , являются операторами отношения, используемыми для сравнения двух величин; выражение отношения, такое как A B является истинным (TRUE), если значение A не равно B, в противном случае — ложным (FALSE).

В алгоритмических описаниях используются следующие идентификаторы:

OperandSize
Представляет собой атрибут размера операнда команды, который может быть 16- или 32-битным.

AddressSize
Представляет собой атрибут размера адреса, который может быть 16 или 32-битным. Например:

IF(команда CMPSW)
   THEN OperandSize = 16;
   ELSE
      IF(команда CMPSD)
         THEN OperandSize = 32;
      FI;
FI;

Пример указывает на то, что атрибут размера операнда зависит от используемой формы команды CMPS. Описание атрибутов размера адреса и размера операнда приведено выше.

StackAddrSize
Представляет собой соответствующий команде атрибут размера адреса стека, который может быть 16 или 32-битным.

SRC
Представляет собой операнд-источник. Из двух операндов команды, SRC обычно является правым (по мнемонике) операндом .

DEST
Представляет собой операнд-назначение. Из двух операндов команды, DEST обычно является левым (по мнемонике) операндом.

LeftSRC, RightSRC
Представляют собой операнды-источники (соответственно, левый и правый по мнемонике). Применяются в случае, если в команде оба операнда являются источниками.

eSP
Представляет собой, либо регистр SP, либо регистр ESP, в зависимости от установки бита B дескриптора текущего сегмента стека, т.е. от значения StackAddrSize при выполнении команды. SP используется, когда StackAddrSize = 16, ESP — StackAddrSize = 32.

 

Функции, используемые в описании алгоритма:

Trunkate_to_16bits(величина)
Уменьшает размерность величины до 16 бит, отбрасывая старшие биты, если это необходимо.

Addr(операнд))
Возвращает эффективный адрес операнда. Вычисление эффективного адреса производится без добавления базы сегмента, т.е сам эффективный адрес — это абсолютное смещение от начала сегмента.

ZeroExtended(величина)
Возвращает величину, дополненную нулями до размера операнда команды. Например, если OperandSize = 32, тогда ZeroExtended от однобайтной величины -10 преобразует байт F6h в четырехбайтную величину 000000F6h. Эта функция оставляет величину без изменения в том случае, если атрибут размера операнда и размера величины совпадают.

SignExtended(величина)
Возвращает величину, знакорасширенную до размера операнда команды. Например, если OperandSize = 32, тогда SignExtended от однобайтной величины -10 преобразует байт F6h в четырехбайтную величину FFFFFFF6h. Эта функция оставляет величину без изменения в том случае, если атрибут размера операнда и размер величины совпадают.

Push(value)
Помещает величину в стек. Количество байтов, помещаемых в стек, определяется атрибутом размера операнда команды. Push действует следующим образом:

IF StackAddrSize = 16
   THEN
      IF OperandSize = 16
         THEN
            SP = SP - 2;
            SS:[SP] = value;
         ELSE (* OperandSize = 32 *)
            SP = SP - 4;
            SS:[SP] = value;
      FI;
   ELSE (* StackAddrSize = 32 *)
      IF OperandSize = 16
         THEN
            ESP = ESP - 2;
            SS:[ESP] = value;
         ELSE (* OperandSize = 32 *)
            ESP = ESP - 4;
            SS:[ESP] = value;
      FI;
FI;

Иногда для указания того, что в стек помещается именно четырехбайтная величина, пишется не Push(value) а Pushd(value).

Pop()
Возвращает величину из вершины стека. Выражение EAX = Pop() помещает в EAX 32-битную величину, которую Pop() берет из вершины стека. Pop() может возвращать как слова, так и двойные слова, в зависимости от значения атрибута размера операнда. Pop() действует следующим образом:

IF StackAddrSize = 16
   THEN
      IF OperandSize = 16
         THEN
            ret val = SS:[SP]; (* Двухбайтная величина *)
            SP = SP + 2;
         ELSE (* OperandSize = 32 *)
            ret val = SS:[SP]; (* Четырехбайтная величина *)
            SP = SP + 4;
      FI;
   ELSE (* StackAddrSize = 32 *)
      IF OperandSize = 16
         THEN
            ret val = SS:[ESP]; (* Двухбайтная величина *)
            ESP = ESP + 2;
         ELSE (* OperandSize = 32 *)
            ret val = SS:[ESP]; (* Четырехбайтная величина *)
            ESP = ESP + 4;
      FI;
FI;
RETURN(ret val); (* Возвращает слово или двойное слово *)

 

Pop(ST)
Используется при описании команд с плавающей запятой и обозначает выборку значения из регистрового стека FPU.

Bit[BitBase, BitOffset]
Возвращает значение бита из строки битов, которая является последовательностью битов в памяти или в регистре. Нумерация битов идет в порядке возрастания и начинается с самого младшего бита содержимого регистров или памяти. Слово в памяти хранится таким образом, что младший байт слова располагается по меньшему адресу, чем старший. Смещение бита (BitOffset) может принимать значения от 0 до 31, если в качестве базового операнда (BitBase) используется регистр. Это смещение адресует бит в указанном регистре. На рис. 6.1. приведен пример Bit[EAX,21].

 

Смещение BitOffset для выражения Bit[EAX,21]

Рис. 6.1. Смещение BitOffset для выражения Bit[EAX,21]

 

Смещение бита может принимать значения от –2 Гбит до +2 Гбит в том случае, если BitBase является адресом памяти. Искомый бит находится под Offset MOD 8 в байте по адресу (BitBase + (BitOffset DIV 8)), где DIV — целочисленное деление со знаком и округлением в сторону -∞ , а MOD возвращает положительное число. Это показано на рис. 6.2.

 

Индексация бита памяти

Рис. 6.2. Индексация бита памяти

 

I-O-Permission(I-O-Address, width)
Возвращает значение TRUE или FALSE в зависимости от значения маски разрешения ввода-вывода и других факторов. Эта функция работает следующим образом:

IF (TSS 16-битный) THEN RETURN (FALSE); FI;
Ptr = [Tss + 66]; (* Выбирается указатель битовой карты *)
BitStringAddr = CHR(I-O-Address, 3) + Ptr;
MaskShift = I-O-Address AND 7;
CASE width OF:
   BYTE: nBitMask = 1;
   WORD: nBitMask = 3;
   DWORDE: nBitMask = 15;
ESAC;
mask = SHL(nBitMask, MaskShift);
CheckString = [BitStringAddr] AND mask;
IF CheckString = 0;
   THEN RETURN(TRUE);
   ELSE RETURN(FALSE);
FI;

 

Switch-Tasks
Это функция переключения задачи.

 

Особые ситуации защищенного режима:

В этом пункте описываются особые ситуации, которые могут иметь место при выполнении команды в защищенном режиме. Все особые ситуации обозначаются следующим образом: вначале идет знак #, затем две буквы английского алфавита, после чего в скобках может присутствовать код ошибки. Например, #GP(0) обозначает особую ситуацию "ошибка общей защиты" с кодом ошибки равным нулю.

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

Особые ситуации режима реальной адресации:

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

Особые ситуации режима V86:

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

 

Замечание:

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