Intel REX кодирование PUSH - PullRequest
       91

Intel REX кодирование PUSH

0 голосов
/ 04 февраля 2019

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?
  • Есть ли лучшая документация, которая, возможно, излагает эти процессы поэтапно, а не заставляет вас переходить между несколькими страницами из таблицы в таблицу?

1 Ответ

0 голосов
/ 05 февраля 2019

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

Краткие формы push reg / pop reg включают 3-битный регистровый код в байт кода операции .Вот что означает 50 + rq.(В отличие от кодировки FF /6 push r/m64, которая использует ModRM; вы можете кодировать операнд-регистр с этим, чтобы сделать инструкцию длиннее, но обычно вы когда-либо будете использовать этодля push qword [rdi] или еще чего-нибудь).

Это тот же формат, что и 16/32-битный, поэтому x86-64 нужен дополнительный бит (из префикса REX) для кодирования одного из "новые "/ старшие регистры, которые имеют 4-битные коды с установленным старшим битом.

OSdev пропустил этот случай и упомянул только ModRM.rm и SIB.base.


В инструкции Intel vol.2 в формате PDF документируется кодировка:

3.1.1.1 Столбец кода операции в сводной таблице инструкций (инструкции без префикса VEX)

  • ...

  • + rb , + rw , + rd , + ro - указано младшие 3 бита байта кода операции используются для кодирования операнда регистра без байта modR / M.Инструкция перечисляет соответствующее шестнадцатеричное значение байта кода операции с младшими 3 битами как 000b.В не 64-битном режиме код регистра, от 0 до 7, добавляется к шестнадцатеричному значению байта кода операции. В 64-битном режиме указывает четырехбитовое поле REX.b, а поле opcode [2: 0] кодирует операнд регистра команды. «+ ro» применимо только в 64-битном режиме.См. Таблицу 3-1 для кодов.

Таблица 3-1 использует ту же схему кодирования, что и номера регистров в ModRM и SIB, что неудивительно, но Intel старается изо всех сил и имеетполная таблица всех целочисленных регистров для всех размеров операндов.Включая AH / BH / CH / DH, потому что mov ah, 1 может использовать 2-байтовую краткую форму.

Я извлек соответствующие строки из столбца «Регистр четырех слов (только для 64-битного режима)»:

From Intel's Table 3-1. Register Codes Associated With +rb, +rw, +rd, +ro
        reg    REX.B  Reg Field
        RBX    None    3

        RBP    None    5

        R12    Yes     4
        R13    Yes     5

Интересный факт: в руководстве Intel они фактически используют 50 + rd вместо 50 + ro для PUSH r64, так же, как для push r32 в 32-битном режиме.https://www.felixcloutier.com/x86/push.


Соответствует ли это аналогичным инструкциям, таким как pop?(И как я узнаю, какие инструкции поддерживают это? Работает ли это для всех инструкций с кодами операций вида XX + xx?)

Да.push/pop reg, mov reg,imm и xchg eax, r32 / xchg rax, r64 все используют одну и ту же кодировку с 3 битами кода операции для кодирования регистра.

Было бы хорошо, если бы у нас были эти 8 xchg коды операциивернемся к чему-то более полезному (например, к более компактным префиксам VEX или EVEX в 64-битном режиме), но этот корабль отплыл, когда AMD играла в него консервативно с AMD64, в основном сохраняя машинный код максимально похожим на 32-битный режим.Однако они восстановили коды операций 0x4? inc/dec reg для использования в качестве префиксов REX.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...