В x86-64 Tour of Intel Manuals я прочитал
Возможно, самым удивительным фактом является то, что такая инструкция, как
MOV EAX, EBX
автоматически обнуляет старшие 32 битаRAX
регистра.
В документации Intel (3.4.1.1 Регистры общего назначения в 64-битном режиме в ручной базовой архитектуре), цитируемой в том же источнике, говорится:
- 64-битные операнды генерируют 64-битный результат в регистре общего назначения назначения.
- 32-битные операнды генерируют 32-битный результат с расширением нулями до 64-битного результата в целевом регистре общего назначения.
- 8-битные и 16-битные операнды генерируют 8-битный или 16-битный результат. Старшие 56 бит или 48 бит (соответственно) регистра назначения общего назначения не изменяются в ходе операции. Если результат 8-битной или 16-битной операции предназначен для вычисления 64-битного адреса, явно расширьте регистр знаками до полных 64 бит.
В сборках x86-32 и x86-64 16-битные инструкции, такие как
mov ax, bx
не показывайте такого "странного" поведения, когда верхнее слово eax обнуляется.
Таким образом: какова причина, по которой было введено это поведение? На первый взгляд это кажется нелогичным (но, возможно, причина в том, что я привык к особенностям сборки x86-32).
r32
операндом назначения обнуляют высокий 32, а не объединяются. Например, некоторые ассемблеры заменят его pmovmskb r64, xmm
на pmovmskb r32, xmm
, сохранив REX, потому что 64-битная конечная версия ведет себя идентично. Несмотря на то, что в разделе «Работа» руководства перечислены все 6 комбинаций 32/64-битного источника и 64/128/256-битного источника отдельно, неявное нулевое расширение формы r32 дублирует явное нулевое расширение формы r64. Мне любопытна реализация HW ...
xor eax,eax
или xor r8d,r8d
- лучший способ обнулить RAX или R8 (сохранение префикса REX для RAX, а 64-битный XOR даже не обрабатывается специально в Silvermont). Связанный: Как именно работают частичные регистры на Haswell / Skylake? Написание AL, кажется, имеет ложную зависимость от RAX, а AH непоследователен