- PVSM.RU - https://www.pvsm.ru -
Сегодня я хочу рассказать вам о префиксах в системе команд Intel IA-32 в 32- и 64-битных вариантах (также именуемых как x86 и x86_64). Но для начала напомню вкратце общую структуру IA-32 инструкции:
Более подробное описание структуры инструкции можно найти в статье «Дизассемблер своими руками» [1] и, конечно же, в Intel 64 and IA-32 Architectures Software Development Manuals [2]. В данной статью будет рассказываться об IA-32 префиксах, особенностях, связанных с их использованием, а также тенденций в их развитии.
Практически с самых первых процессоров Intel в системе команд IA-32 начали использоваться однобайтные префиксы. О них уже было написано на Хабре [1], по этой причине я про них рассказывать не буду.
С появлением расширения 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 бит.
В определенный момент появилась необходимость в поддержке 64-битного адресного пространства и расширения числа адресуемых регистров. С этой задачей успешно справились разработчики AMD, добавив префикс, названный REX
. Данный префикс также является однобайтными, и имеет вид 0x4*
. Его биты используются для расширения уже существующих полей, кодируемых в Mod_R/M
байте, а также ширины операнда. На рисунке приведен пример использования REX
префикса для адресации регистров.
Стоит отметить несколько особенностей, связанных с использованием этого префикса. Кодировка 0x4*
соответствует префиксу только в 64-битном режиме, во всех остальных режимах она соответствует вариантам инструкций INC/DEC
. Интересным свойством данного префикса является то, что он должен быть расположен непосредственно перед байтом опкода, в противном случае он игнорируется. Если REX
префикс используется вместе с инструкцией требующей присутствия другого обязательного префикса, он должен быть расположен между этим префиксом и байтом кода операции.
С введением расширения 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
префикса предоставляет следующие преимущества:
XMM
регистров и 256-битных YMM
регистров.REX
префикса для адресации регистров общего назначения (R8
– R15
), векторных регистров XMM8
– XMM15
(YMM8
– YMM15
). VEX
позволяет кодировать те же поля, что и REX
, и, вдобавок, несколько новых.
Следуют отметить, что использование VEX
префикса вместе с некоторыми однобайтными префиксами (0xf0
, 0x66
, 0xf2
, 0xf3
, REX
) запрещено и приводит к исключению #UD
.
Не так давно Intel анонсировал появление нового расширения набора команд с названием AVX3
или AVX512
. С появлением этого расширения также появился и новый префикс, получивший название EVEX
. Его описание можно найти в Intel Architecture Instruction Set Extensions Programming Reference [3].
Он представляет собой усовершенствованный вариант VEX
префикса, имеет длину уже в 4 байта и начинается с байта 0x62
, который во всех режимах, кроме 64-битного соответствует инструкции BOUND
, редко используемой в современных программах.
Приведу некоторые, на мой взгляд, интересные особенности EVEX
префикса:
LL`
– необходимые для поддержки векторов размером 128, 256 и 512 бит.ZMM8
— ZMM31
.EVEX.aaa
.EVEX.mm
– эквивалент поля VEX.m-mmmm
, но занимает два бита вместо пяти. В заключение хочется отметить некоторые причины появления столько сложной и, местами, не логичной системы команд. История развития системы команд Intel IA-32 начинается в 70-х годах прошлого столетия, когда ни о каких 64-битных режимах не было и речи. Кроме Intel существенный вклад в эволюцию IA-32 внесла компания AMD. Много усилий было потрачено на поддержание обратной совместимости между различными моделями процессоров. Множество интересных фактов, связанных с развитием архитектуры IA-32 можно найти в статье A. Fog’a [4].
Спасибо пользователю Atakua [5] за комментарии к черновикам этой статьи.
P.S. Все иллюстрации взяты из Intel 64 and IA-32 Architectures Software Development Manuals [2].
Автор: yulyugin
Источник [6]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/47742
Ссылки в тексте:
[1] «Дизассемблер своими руками»: http://habrahabr.ru/post/128042
[2] Intel 64 and IA-32 Architectures Software Development Manuals: http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html
[3] Intel Architecture Instruction Set Extensions Programming Reference: http://download-software.intel.com/sites/default/files/319433-015.pdf
[4] A. Fog’a: http://www.agner.org/optimize/blog/read.php?i=25
[5] Atakua: http://habrahabr.ru/users/atakua/
[6] Источник: http://habrahabr.ru/post/200598/
Нажмите здесь для печати.