МодР/М
Байт ModR/M является важной частью кодирования инструкций для набора команд x86 .
Описание
[ редактировать ]Коды операций в x86 обычно однобайтовые, хотя существуют двухбайтовые инструкции и префиксы. ModR/M — это байт, следующий за кодом операции, который определяет два операнда для инструкции. [ 1 ] : §2.1 Один операнд является регистром, а другой — операндом регистра или памяти. Формат:
Кусочек | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Использование | ПРОТИВ | РЕГ | Р/М |
Поле REG определяет операнд регистра согласно следующей таблице:
РЕГ | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
---|---|---|---|---|---|---|---|---|
Байтовые операции | АЛ | КЛ | ДЛ | БЛ | АХ | СН | ДХ | ЧД |
Операции со словами | (Е)АХ | (Е)CX | (Э)ДХ | (Е)ВХ | (Э)СП | (Е) БП | (НУ ДА | (Э)ДИ |
Байтовые операции с REX ( см. ниже ) | АЛ | КЛ | ДЛ | БЛ | СПЛ | БПЛ | SIL | ЯЗЫК |
Инструкции, которые принимают только один операнд, не используют это поле, а вместо этого используются в качестве дополнительных битов кода операции, позволяя восьми таким инструкциям совместно использовать один байт кода операции. В списках кодов операций они указываются косой чертой после кода операции ( /) и цифра 0-7. [ 1 ] : §3.1.1.1 Например, код операции для увеличения байта: FE/0
[ 1 ] : 3-449 [ 2 ] : 183 , а для уменьшения байта это FE/1
. [ 1 ] : 3-283 [ 2 ] : 171
Поле MOD определяет режим адресации для операнда регистра/памяти, а поле R/M указывает используемый регистр. Если поле MOD равно 11, поле R/M определяет регистр так же, как и поле REG.
Для других значений поля MOD указывается операнд памяти, а базовый регистр указывается полем R/M, к которому добавляется смещение. Если MOD равен 00, смещение равно нулю. Если MOD равен 01, используется 8-битное знаковое смещение. Если MOD равен 10, используется смещение размером в слово (16 или 32 бита, в зависимости от режима работы).
Интерпретация поля R/M как базового регистра сильно различается между 16- и 32-битными режимами адресации.
В 16-битном режиме восемь возможных значений поля R/M определяют базовый регистр следующим образом: [ 1 ] : Таблица 2-1 [ 2 ] : Таблица А-33 [ 3 ] [ 4 ]
- 000: [BX + SI + дисп0/8/16]
- 001: [BX+DI+disp0/8/16]
- 010: [BP + SI + дисп0/8/16]
- 011: [BP+DI+disp0/8/16]
- 100: [SI + дисп0/8/16]
- 101: [DI+disp0/8/16]
- 110: [BP + дисп0/8/16]
- 111: [ВХ + дисп0/8/16]
где «disp0/8/16» — это смещение, заданное битами MOD.
В качестве особого исключения комбинация MOD=00 R/M=110, которая обычно определяет [BP + disp0], вместо этого указывает 16-битный адрес [disp16] вообще без базы регистров. Для адреса [BP+0] используйте 1-байтовую форму смещения со смещением 0.
В результате получается полный набор комбинаций:
Р/М | ПРОТИВ | |||
---|---|---|---|---|
00 | 01 | 10 | 11 | |
000 | [ВХ+СИ] | [ВХ+СИ+дисп8] | [ВХ+СИ+дисп16] | АЛ/АКС |
001 | [ВХ+ДИ] | [ВХ+DI+дисп8] | [ВХ+DI+дисплей16] | КЛ/СХ |
010 | [БП+СИ] | [БП+СИ+дисп8] | [БП+СИ+дисп16] | ДЛ/ДХ |
011 | [БП+ДИ] | [БП+ДИ+дисп8] | [БП+ДИ+дисп16] | БЛ/ВХ |
100 | [И] | [СИ+дисп8] | [ДА+дисп16] | АХ/СП |
101 | [ОТ] | [DI+дисп8] | [DI+дисп16] | Ч/БП |
110 | [дисп16] | [БП+дисп8] | [БП+дисп16] | ДХ/СИ |
111 | [ВХ] | [ВХ+дисп8] | [ВХ+дисп16] | ЧД/ДИ |
В 32-битном режиме имеется много отличий. [ 1 ] : Таблица 2-2 [ 2 ] : Таблица А-34 [ 3 ] [ 4 ] Во-первых, случай MOD=10 определяет 32-битное смещение (disp32). Во-вторых, поле R/M указывает только один базовый регистр, используя ту же кодировку, что и поле REG. Есть два исключения:
- Как и в 16-битном режиме, кодировка [EBP + disp0] заменяется голым disp32. Адрес [EBP+0] должен использовать кодировку [EBP+disp8] со значением disp8, равным 0. Однако обратите внимание, что в 32-битном режиме кодировка для этого — MOD=00 R/M=101.
- Кодировка MOD≠11 R/M=100 не определяет [ESP] в качестве базы, как можно было бы ожидать, но вместо этого указывает наличие § SIB-байта , и результирующее значение SCALE*INDEX+BASE должно использоваться для вычисления адреса. .
Р/М | ПРОТИВ | |||
---|---|---|---|---|
00 | 01 | 10 | 11 | |
000 | [ЕАХ] | [EAX+дисп8] | [EAX+дисп32] | АЛ/АХ/ЕАКС |
001 | [ЭКХ] | [ECX+дисп8] | [ECX+disp32] | CL/CX/ECX |
010 | [EDX] | [EDX+дисп8] | [EDX+дисп32] | ДЛ/ДХ/EDX |
011 | [ЕВХ] | [EBX+дисп8] | [EBX+disp32] | БЛ/ВХ/ЕВХ |
100 | [ СИБ ] |
[ СИБ +disp8] | [ СИБ +disp32] | АХ/СП/ЭСП |
101 | [дисп32] | [EBP+disp8] | [EBP+disp32] | Ч/Б/ЕБП |
110 | [КАК] | [ESI+дисп8] | [ESI+disp32] | ДХ / СИ / ЭСИ |
111 | [ЭДИ] | [EDI+disp8] | [EDI+disp32] | БХ/ДИ/ЭОД |
Комбинация MOD=00 R/M=100, которая определяет байт SIB без смещения, имеет аналогичный особый случай, если базовый регистр закодирован как 101 (EBP). В этом случае базовый регистр опускается, но используется смещение слов, создавая режим адресации [SCALE*INDEX+disp32].
SIB-байт
[ редактировать ]Байт SIB — это необязательный байт постоперационного кода в сборке x86 на i386 и более поздних версиях, используемый для комплексной адресации.
Байты SIB форматируются аналогично байтам ModR/M и принимают форму (scale * index) + base + displacement
, где МАСШТАБ равен 1, 2, 4 или 8. BASE и INDEX кодируют регистры. [ 5 ] Смещение представляет собой постоянное смещение, размер которого обычно задается полем MOD, которое кодируется после байта SIB и добавляется к конечному адресу. [ 3 ]
Префикс REX позволяет байту SIB использовать 16 целочисленных регистров. [ 1 ]
Общий формат следующий:
Кусочек | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Использование | ШКАЛА | ИНДЕКС | БАЗА |
Однако есть два исключения:
- ИНДЕКС ESP запрещен. Кодировка INDEX=100 обозначает нулевой индекс независимо от поля SCALE. Обычно в режиме адресации без индекса просто используется чистый байт ModR/M вообще без байта SIB, но это необходимо для кодирования адреса, относительного ESP ([ESP+disp0/8/32]).
- Когда MOD=00, значение BASE равное 101, которое указывает EBP с нулевым смещением, вместо этого указывает отсутствие базового регистра и 32-битное смещение. Если требуется EBP с нулевым смещением, его необходимо закодировать с помощью disp8 со значением 0. Это аналогично обработке случая MOD=00 R/M=101.
В 64-битном режиме MOD=00 R/M=101 переназначается для кодирования относительных адресов [RIP+disp32], поэтому абсолютный адрес [disp32] должен кодироваться с использованием байта SIB с обоими этими исключениями.
64-битные изменения
[ редактировать ]AMD 64-битное расширение исходного набора команд вносит относительно мало изменений в 32-битную адресацию, наиболее важным из которых является то, что в длинном режиме 64-битная адресация используется по умолчанию. Для вычисления адреса используются 64-битные регистры (RAX, RBX, RCX и т. д.), а не 32-битные регистры. Смещение не расширяется до 64 бит; MOD=11 продолжает указывать 32-битное смещение, которое расширяется по знаку до 64 бит. [ 2 ] : §1.5
Это можно изменить с помощью префикса переопределения размера адреса. 0x67
, который меняется на 32-битную адресацию для следующей инструкции. [ 2 ] : §1.2.3
Вторым важным дополнением является префикс REX . [ 2 ] : §1.2.7,§1.4.4 В длинном режиме коды операций, старшие четыре бита которых 0100
(десятичные 4) — это префикс REX, который предоставляет дополнительный бит для каждого поля регистра следующей инструкции, удваивая количество доступных регистров процессора с восьми до шестнадцати. [ 2 ] : §1.4 В частности, четыре младших бита:
- W: Если установлено, операция выполняется с 64-битными операндами.
- R: расширяет поле REG до 4 бит.
- X: расширяет поле INDEX байта SIB (если оно присутствует) до 4 битов.
- B: расширяет поле R/M (или BASE байта SIB, если MOD≠11 R/M=100) до 4 битов.
Префикс REX имеет еще один эффект: префикс REX меняет способ обращения к байтовым регистрам. Без префикса доступны байтовые регистры AL/CL/DL/BL, затем AH/CH/DH/BH. При наличии префикса REX даже префикс REX 01000000
байтовые инструкции последовательно обращаются к младшему байту соответствующих словных регистров, поэтому доступный байт становится AL/CL/DL/BL/SPL/BPL/SIL/DIL. [ 2 ] : §2.3.1
Третье существенное изменение — адресация, относящаяся к RIP. [ 2 ] : §1.7 Тогда кодировка MOD=00 R/M=101, которая определяет адрес disp32 (без базового регистра) в 32-битном режиме, указывает [RIP+disp32] в длинном режиме. При использовании префикса переопределения размера адреса это становится [EIP+disp32]. [ 2 ] : §1.7.3 Абсолютный режим [disp32] можно получить, используя MOD=00 R/M=100, чтобы принудительно использовать байт SIB, за которым следует байт SIB с BASE=101 и INDEX=100. [ 2 ] : §1.7.1
Для кодировок адресации особого случая R/M=100 (для принудительного использования байта SIB), MOD=00 R/M=101 (замена RIP+disp32) и MOD=00 R/M=100 BASE=101 (замена disp32) ), префикс REX.B не учитывается . [ 2 ] : §1.8.2 Эти специальные кодировки также применимы к регистрам R12 (двоичный 1100) и R13 (двоичный 1101). [ 4 ] и должны использоваться те же самые, немного более длинные кодировки. Это связано с тем, что эти исключения изменяют размер закодированной инструкции, поэтому их необходимо декодировать очень быстро, чтобы можно было найти следующую инструкцию.
Однако особый случай, когда INDEX=100 подавляет индексный регистр (масштабирование RSP запрещено), не учитывает бит REX.X; возможно масштабирование R12. [ 2 ] : §1.8.2 Это происходит по двум причинам:
- альтернативного способа кодирования индексации с помощью R12 не существует, поэтому это будет серьезным ограничением, и
- исключение изменяет вычисленный адрес , но не размер закодированной инструкции , поэтому в конвейере команд остается больше времени для разрешения особого случая.
Ссылки
[ редактировать ]- ^ Перейти обратно: а б с д и ж г час я дж Корпорация Intel (сентябрь 2016 г.). «Руководство разработчика программного обеспечения для архитектур Intel® 64 и IA-32, том 2A» (PDF) . Проверено 19 августа 2024 г.
- ^ Перейти обратно: а б с д и ж г час я дж к л м н тот п д Усовершенствованные микроустройства (март 2024 г.). «Руководство программиста по архитектуре AMD64, том 3: универсальные и системные инструкции» (PDF) . обр. 3.36 . Проверено 19 августа 2024 г.
- ^ Перейти обратно: а б с д и ж «Справочное руководство программиста 80386 — раздел 17.2» . www.scs.stanford.edu . Проверено 28 июля 2022 г.
- ^ Перейти обратно: а б с д и ж «Кодирование инструкций X86-64» . OSDev.org . Проверено 19 августа 2024 г.
- ^ Хартман, Крис. «Инструкции по кодированию» . Университет Аляски в Фэрбенксе . Проверено 28 июля 2022 г.