Сегодня я хочу рассказать вам о префиксах в системе команд Intel IA-32 в 32- и 64-битных вариантах (также именуемых как x86 и x86_64). Но для начала напомню вкратце общую структуру IA-32 инструкции:

Более подробное описание структуры инструкции можно найти в статье «Дизассемблер своими руками» и, конечно же, в Intel 64 and IA-32 Architectures Software Development Manuals. В данной статью будет рассказываться об IA-32 префиксах, особенностях, связанных с их использованием, а также тенденций в их развитии.
Практически с самых первых процессоров Intel в системе команд IA-32 начали использоваться однобайтные префиксы. О них уже было написано на Хабре, по этой причине я про них рассказывать не буду.
С появлением расширения
Не сложно заметить, что кодировки этих инструкций отличаются только префиксом. Опкод у них совпадает –
В определенный момент появилась необходимость в поддержке 64-битного адресного пространства и расширения числа адресуемых регистров. С этой задачей успешно справились разработчики AMD, добавив префикс, названный

Стоит отметить несколько особенностей, связанных с использованием этого префикса. Кодировка
С введением расширения

Поля
Использование
Следуют отметить, что использование
Не так давно Intel анонсировал появление нового расширения набора команд с названием

Он представляет собой усовершенствованный вариант
Приведу некоторые, на мой взгляд, интересные особенности
В заключение хочется отметить некоторые причины появления настолько сложной и, местами, не логичной системы команд. История развития системы команд Intel IA-32 начинается в 70-х годах прошлого столетия, когда ни о каких 64-битных режимах не было и речи. Кроме Intel существенный вклад в эволюцию IA-32 внесла компания AMD. Много усилий было потрачено на поддержание обратной совместимости между различными моделями процессоров. Множество интересных фактов, связанных с развитием архитектуры IA-32 можно найти в статье A. Fog’a.
Спасибо пользователю Atakua за комментарии к черновикам этой статьи.
P.S. Все иллюстрации взяты из Intel 64 and IA-32 Architectures Software Development Manuals.

- Префиксы. Могут отсутствовать. Может присутствовать сразу несколько.
- Опкод. Может состоять из одного, двух или трех байтов.
- Mod_R/M байт. Используется для адресации операндов. Может отсутствовать в кодировке, если инструкция не имеет явных операндов.
- SIB (Scale Index Base) байт. Второй байт, использующийся для адресации операндов в памяти. Может отсутствовать.
- Байт смещения адреса (англ. displacement). 1, 2, 4 или ни одного байта.
- Константа (англ. immediate). 1, 2, 4 или ни одного байта.
Более подробное описание структуры инструкции можно найти в статье «Дизассемблер своими руками» и, конечно же, в Intel 64 and IA-32 Architectures Software Development Manuals. В данной статью будет рассказываться об IA-32 префиксах, особенностях, связанных с их использованием, а также тенденций в их развитии.
Однобайтные префиксы
Практически с самых первых процессоров Intel в системе команд IA-32 начали использоваться однобайтные префиксы. О них уже было написано на Хабре, по этой причине я про них рассказывать не буду.
Обязательные префиксы
С появлением расширения
SSE часть однобайтных префиксов, а именно 0xf2, 0xf3, 0x66 в некоторых случаях стали иметь смысл части опкода. Появились так называемые обязательные префиксы (англ. mandatory prefixes). Примеры таких инструкций приведены ниже.| Кодировка | Инструкция | Обязательный префикс |
|---|---|---|
0x0f 0x10 |
MOVUPS |
- |
0xf2 0x0f 0x10 |
MOVSD |
0xf2 |
0xf3 0x0f 0x10 |
MOVSS |
0xf3 |
0x66 0x0f 0x10 |
MOVUPD |
0x66 |
Не сложно заметить, что кодировки этих инструкций отличаются только префиксом. Опкод у них совпадает –
0x0f 0x10. При этом семантика у этих инструкций различна. Например, MOVSD копирует из одного операнда в другой 64 бита, а MOVUPD – 128 бит.Префикс REX
В определенный момент появилась необходимость в поддержке 64-битного адресного пространства и расширения числа адресуемых регистров. С этой задачей успешно справились разработчики AMD, добавив префикс, названный
REX. Данный префикс также является однобайтным, и имеет вид 0x4*. Его биты используются для расширения уже существующих полей, кодируемых в Mod_R/M байте, а также ширины операнда. На рисунке приведен пример использования REX префикса для адресации регистров.
Стоит отметить несколько особенностей, связанных с использованием этого префикса. Кодировка
0x4* соответствует префиксу только в 64-битном режиме, во всех остальных режимах она соответствует вариантам инструкций INC/DEC. Интересным свойством данного префикса является то, что он должен быть расположен непосредственно перед байтом опкода, в противном случае он игнорируется. Если REX префикс используется вместе с инструкцией требующей присутствия другого обязательного префикса, он должен быть расположен между этим префиксом и байтом кода операции.Префикс VEX
С введением расширения
AVX в системе команд IA-32 появился новый префикс, названный VEX. Он уже не однобайтный. Он может состоять либо из двух, либо из трех байт в зависимости от первого байта префикса. 0xc4 и 0xc5 соответственно.
Поля
R, X, B, W несут тот же смысл, что и соответствующие поля REX префикса. Поле pp предоставляет функциональность, эквивалентную обязательным SIMD префиксам (например, b01 = 0x66). А поле m-mmmm может соответствовать целым двум байтам опкода (например, 0b00011 = 0x0f 0x3a). Поле L определяет длину вектора: 0 – 128 бит, 1 – 256 бит.Использование
VEX префикса предоставляет следующие преимущества:- Поддержка до четырех операндов.
- Поддержка 128-битных
XMMрегистров и 256-битныхYMMрегистров. - Сжатие кодировки уже введенных инструкций.
- Удаление необходимости использования
REXпрефикса для адресации регистров общего назначения (R8–R15), векторных регистровXMM8–XMM15(YMM8–YMM15).VEXпозволяет кодировать те же поля, что иREX, и, вдобавок, несколько новых.
Следуют отметить, что использование
VEX префикса вместе с некоторыми однобайтными префиксами (0xf0, 0x66, 0xf2, 0xf3, REX) запрещено и приводит к исключению #UD.Префикс EVEX
Не так давно Intel анонсировал появление нового расширения набора команд с названием
AVX3 или AVX512. С появлением этого расширения также появился и новый префикс, получивший название EVEX. Его описание можно найти в Intel Architecture Instruction Set Extensions Programming Reference.
Он представляет собой усовершенствованный вариант
VEX префикса, имеет длину уже в 4 байта и начинается с байта 0x62, который во всех режимах, кроме 64-битного соответствует инструкции BOUND, редко используемой в современных программах. Приведу некоторые, на мой взгляд, интересные особенности
EVEX префикса:- Два бита для длины вектора –
LL`– необходимые для поддержки векторов размером 128, 256 и 512 бит. - Поддержка адресации новых 512-битных регистров
ZMM8—ZMM31. - Поддержка регистров маски операндов (англ. opmask registers). Поле
EVEX.aaa. EVEX.mm– эквивалент поляVEX.m-mmmm, но занимает два бита вместо пяти.
Заключение
В заключение хочется отметить некоторые причины появления настолько сложной и, местами, не логичной системы команд. История развития системы команд Intel IA-32 начинается в 70-х годах прошлого столетия, когда ни о каких 64-битных режимах не было и речи. Кроме Intel существенный вклад в эволюцию IA-32 внесла компания AMD. Много усилий было потрачено на поддержание обратной совместимости между различными моделями процессоров. Множество интересных фактов, связанных с развитием архитектуры IA-32 можно найти в статье A. Fog’a.
Спасибо пользователю Atakua за комментарии к черновикам этой статьи.
P.S. Все иллюстрации взяты из Intel 64 and IA-32 Architectures Software Development Manuals.