Сборка с использованием регистров rN (r8, r9, ...) имеет больший размер кода, чем другие регистры - PullRequest
0 голосов
/ 09 января 2020

У меня есть вопрос об использовании регистров 'rN' (r8, r9, r10, ....)

Я хочу использовать регистры r8, r9, ... в моей программе (часто используется !) но я обнаружил проблему с размером кода!

Например,

mov eax, DWORD [rdi+4]

равно (8b 47 04) (дизассемблер)

, но когда я использую ' rN 'регистров, это разные!

mov eax, DWORD [r9+4]

это равно (41 8b 41 04) (у него есть дополнительный BYTE (префикс)!)

, поэтому с использованием rN регистры имеют больший размер кода, чем другие регистры !!!!!!!!!!!!!!!!!!! во-первых, почему? !!!

Во-вторых, кроме проблемы размера кода, есть ли другие проблемы, такие как (CACHE, CYCLE, ...), если мы использовать регистры rN (r8, r9, r10, ...) вместо других регистров?

1 Ответ

2 голосов
/ 09 января 2020

, поэтому использование регистров rN имеет больший размер кода, чем при использовании других регистров

Да, это хорошо известный и документированный факт. Префиксы REX являются одним из наиболее важных изменений в машинном коде x86-64 по сравнению с более ранними режимами, и на этот вопрос стоит ответить только для части производительности (см. Ниже).

машинный код x86 имеет только 3-битные поля для регистров. 4-й бит, если он не равен нулю, должен исходить из префикса REX.

Это то, для чего AMD64 перепрофилировала байты кода операции 0x4? (в 32-битном машинном коде они 1- byte inc / de c reg инструкции).

Разрешение декодирования x86-64 на тех же транзисторах, что и в декодировании в 16/32-битном режиме, вместо необходимости полного нового блока декодера во внешнем интерфейсе AMD предпочла не перепроектировать машинный код x86 с нуля. Поэтому они застряли с 3-битными полями для регистров и должны были использовать префиксный байт.

Прочтите руководство Intel vol.2 для получения дополнительной информации о префиксах REX. Или https://wiki.osdev.org/X86-64_Instruction_Encoding#REX_prefix содержит некоторые полезные вещи, включая детали того, что означают эти биты. Это также объясняет:

Префикс REX должен быть закодирован, когда:

  • с использованием размера 64-битного операнда и инструкция не по умолчанию имеет размер 64-битного операнда (большинство по умолчанию инструкции имеют размер 32-битного операнда); или
  • с использованием одного из расширенных регистров (от R8 до R15, от XMM8 до XMM15, от YMM8 до YMM15, от CR8 до CR15 и от DR8 до DR15); или
  • с использованием одного из унифицированных байтовых регистров SPL, BPL, SIL или DIL.

И не может использоваться при использовании AH, CH, BH или DH. (Префикс REX вообще, даже без установленных битов, изменяет значение кодировки для AH на SPL и т. Д.)

(Инструкции с префиксом VEX (например, AVX и некоторые BMI / BMI2) ) или EVEX (AVX512) используют это вместо REX для дополнительных регистровых битов. 2-байтовый VEX может кодировать X / YMM8..15 как пункт назначения или первый источник, без необходимости использовать более широкий 3-байтовый префикс VEX.)


Во-вторых, кроме проблемы размера кода, есть ли другие проблемы, такие как (CACHE, CYCLE, ...), если мы используем регистры rN (r8, r9, r10, ... ) вместо других регистров?

Нет, только размер кода (и для некоторых процессоров общее количество префиксов) . ЦП с кэш-памятью uop в основном не подвержены непосредственному воздействию размера кода , но косвенные эффекты, такие как увеличение занимаемой площади I-кэша (и менее плотная упаковка кэша uop), все еще остаются проблемой. И, конечно, в больших масштабах, с большими двоичными файлами.

Но некоторые процессоры (особенно семейство Silvermont) медленно декодируют инструкции с более чем 3 префиксами, поэтому, например, любая инструкция SSSE3 / SSE4 с префиксом REX глохнет декодер . См. Микроарх Агнера Фога pdf . В Silvermont даже escape-байт опкода 0F для 2-байтовых опкодов считается одним из 3 вместе с обязательными префиксами для кодирования инструкций SIMD.

  401000:       66 0f 38 00 07          pshufb xmm0,XMMWORD PTR [rdi]   # 3 prefixes before the 00 opcode
  401005:       66 41 0f 38 00 00       pshufb xmm0,XMMWORD PTR [r8]    # 4 prefixes

Последний будет слишком медленным в Silvermont. Впрочем, отлично подходит для других процессоров с ограничением в 3 префикса (некоторые AMD IIR C); только в семействе Silvermont байт 0F считается префиксом.

Основные процессоры Intel могут декодировать произвольное количество префиксов без остановки, с учетом только ограничений на количество байтов машинного кода, которое они могут просматривать за тактовый цикл на этапе предварительного декодирования, который находит границы между инструкциями, и на этапе основного декодирования, который превращает до 5 команд (или более с помощью макро-синтеза) в до 5 мопов. (Skylake) Один из них имеет ограничение длины 16 байтов за цикл; IIR C это предварительное декодирование; проверьте руководство Агнер Фог, если это имеет значение.

...