GAS дает следующие кодировки для следующих инструкций:
push rbp # 0x55
push rbx # 0x53
push r12 # 0x41 0x54
push r13 # 0x41 0x55
Из AMD64 spec (стр. 313):
PUSH reg64 50 +rq
Pushконтексты 64-битного регистра в стеке.
Поскольку смещения для rbp
и rbx
равны 5 и 3 соответственно, первые два кодирования имеют смысл.Однако я не понимаю, что происходит с последними двумя кодировками.
Я понимаю, что 0x40-0x4f
является префиксом REX, а 0x41
имеет установленный бит REX.B
(который является либо расширениемMSB MODRM.rm
или SIB.base
, в соответствии с этим внешняя ссылка ).В спецификации упоминается, что для доступа ко всем 16 GPR вам нужно использовать REX, но неясно, где находится отсечение.
Из справочных документов по MODRM и SIB я не думаю, что используется SIB, потому чтоего целью является индексирование с использованием регистра base + offset (хотя, если честно, я не могу точно сказать, как вы различаете MODRM и SIB, учитывая только кодировку).
Итак, я подозреваю, что здесь используется MODRM,Учитывая только push r12
(0x41 0x54
) на данный момент (и учитывая, что r12
имеет смещение 12
), мы имеем:
+----------------+--------------------+
| 0x41 | 0x54 |
+----------------+--------------------+
| REX | MODRM |
+--------+-------+-----+--------+-----+
| Prefix | WRXB | mod | reg | rm |
| 0100 | 0001 | 01 | 01 0 | 100 |
+--------+-------+-----+--------+-----+
REX.B + MODRM.rm = 0b1100 = 12
, так что это будет означать, что эторегистр источника (r12
= смещение 12).Если вы игнорируете все таблицы во внешней (неофициальной) ссылке , REX.R + MODRM.mod + MODRM.reg = 0b00101 = 5
, которая является первым кусочком базы инструкций push 0x50
.
Итак, я думаю, чтоЯ работал с этим в обратном направлении, но я не понимаю, как бы я пришел к кодировке, как 0x41 0x54
.Из ссылки AMD на рис. 1-10 (стр. 54) сноска гласит, что если MODRM.mod = 01 or 10
, то байт «включает смещение, заданное полем смещения инструкции».Возможно, это намекает на то, почему у нас есть смещение инструкции REX.R + MODRM.mod + MODRM.reg = 0b00101 = 5
.Но почему MODRM.mod
часть смещения инструкции?Если оно должно быть включено, то инструкции, принимающие эту форму смещения, ограничиваются префиксами 0b01
или 0x10
.Это не может быть правдой, верно?
tl; dr
- Как на самом деле работает кодирование REX для таких инструкций, как
push
? - Что такоесмещение инструкции для получения префикса REX?(документально подтверждено, что я не могу сделать 0x50 + 12 для
push r12
, как я мог бы для push rbp
или push rbx
?) - Почему
MODRM.mod
включен в префикс базы команд?(Или это вообще правильно?) - Соответствует ли это аналогичным инструкциям, как
pop
?(И как мне узнать, какие инструкции поддерживают это? Работает ли это для всех инструкций, имеющих коды операций вида XX +xx
?) - Где это задокументировано в официальном руководстве?
- КакМогу ли я различить, следует ли за префиксом REX байт MODRM или SIB?
- Есть ли лучшая документация, которая, возможно, излагает эти процессы поэтапно, а не заставляет вас переходить между несколькими страницами из таблицы в таблицу?