Что означают "префиксы инструкций" в современных x86

Чтобы понять, почему Bulldozer был подпаркой, я смотрел превосходную книгу микроархитектуры Agner Fog, в ней на стр. 178 под бульдозером есть этот параграф.

Инструкции с тремя префиксами могут быть декодированы за один такт. Существует очень большой штраф за инструкции с более чем тремя префиксы. Инструкции с 4-7 префиксами занимают 14-15 тактов для декодирования. Инструкции с 8-11 префиксами занимают 20-22 тактовых цикла дополнительно, а инструкции с 12-14 префиксами занимают 27-28 тактов дополнительно. Поэтому не рекомендуется делать инструкции NOP дольше с более чем тремя префиксами. Счет префикса для этого правила включает размер операнда, размер адреса, сегмент, повтор, блокировка, REX и XOP префиксы. Префикс VEX с тремя байтами считается одним, а двухбайтный Префикс VEX не учитывается. Коды выхода (0F, 0F38, 0F3A) не учитываются.

Когда я искал префиксы, я был поражен очень техническими определениями далеко за пределами моих способностей. Или, предположил, что они ограничены до 4 на инструкцию, которая противоречит вышеупомянутому выходу.

Таким образом, может ли кто-нибудь объяснить, что они делают, и почему вы, возможно, захотите сделать ставку до 14+ на инструкцию, а не разбивать ее?

Ответ 1

Обычно вы используете столько, сколько необходимо, с предполагаемой инструкцией и операндами, определяющими это. Ассемблер автоматически выдает некоторые префиксы, а другие - вручную.

Случай, который они упоминают, относится к многобайтовому NOP, который традиционно используется для выравнивания, где идея состоит в том, чтобы использовать одну, но достаточно длинную инструкцию для сохранения ресурсов. По-видимому, оказывается, что использование большего количества префиксов только для того, чтобы сохранить одну команду, может быть хуже, чем использование двух инструкций с меньшим количеством префиксов.

Счет префикса для этого правила включает размер операнда, размер адреса, сегмент, повтор, блокировку, префиксы REX и XOP. Префикс VEX с тремя байтами считается одним, а двухбайтовый префикс VEX не учитывается.

Примеры:

  • размер операнда: может переключаться между 32 и 16-битными регистрами, например. mov ax, [foo] кодируется так же, как mov eax, [foo], но с префиксом 66h
  • размер адреса: может переключаться между размерами адресов 32/16 или 64/32 бит, например. mov [eax], foo кодируется так же, как mov [rax], foo, но с префиксом 67h (в режиме 64 бит)
  • сегмент: можно переопределить используемый сегмент, например. mov [fs:eax], foo кодируется так же, как mov [eax], foo, но с префиксом 64h.
  • repeat: используется со строковыми инструкциями для повторения, например. rep cmpsb кодируется так же, как cmpsb, но с префиксом f3h
  • lock: используется с определенными инструкциями, чтобы сделать их атомарными, например. lock add [foo], 1 кодируется так же, как add [foo], 1, но с префиксом f0h
  • REX.W: используется для переключения на размер 64-разрядного операнда, например. add rax, 1 кодируется так же, как add eax, 1, но с префиксом 48h
  • REX.R, B, X: используются в качестве расширений байта modr/m для доступа к дополнительным регистрам, например. add r8d, 1 совпадает с add eax, 1, но с префиксом 41h
  • XOP, VEX: используется с подмножествами векторных команд

Ответ 2

"Четыре префиксы" заключаются в "префиксных группах":

  • Замок/представитель/REPNE
  • переопределение сегмента
  • переопределение размера операнда
  • переопределение размера адреса

Вы можете повторять префиксы, но вы не можете (можете, но поведение undefined) использовать несколько разных префиксов из одной группы. Хотя это относится только к группам 1 и 2, остальные группы имеют по 1 штуке в каждой.

Что-то вроде 66 66 66 66 66 66 66 66 90 является допустимым (но потенциально медленным для декодирования). 2E 3E 00 00 (переопределение смешивания) не является.

Префиксы стеков могут быть полезны для выравнивания кода, когда байты должны выполняться, в отличие от дополнения с помощью nop, это не требует времени исполнения. Использование слишком большого количества одновременно может стоить времени декодирования.