Почему инструкции x86-64 на 32-разрядных регистрах обнуляют верхнюю часть полного 64-битного регистра?

В x86-64 Обзор руководств Intel Я прочитал

Возможно, самым удивительным фактом является то, что команда типа 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).

Ответ 1

Я не AMD и не выступаю за них, но я бы сделал то же самое. Поскольку обнуление верхней половины не создает зависимости от предыдущего значения, то процессор должен будет ждать. Механизм переименования регистров будет по существу побежден, если бы это не было сделано. Таким образом, вы можете записать быстрый 32-битный код в режиме 64 бит, не требуя явного разрыва зависимостей все время. Без такого поведения каждая 32-битная инструкция в режиме 64 бит должна была бы ждать того, что было раньше, хотя эта высокая часть почти никогда не будет использоваться.

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

Ответ 2

Он просто экономит место в инструкциях и наборе инструкций. Вы можете переместить небольшие немедленные значения в 64-разрядный регистр с помощью существующих (32-разрядных) инструкций.

Это также избавляет вас от необходимости кодировать 8 байтовых значений для MOV RAX, 42, когда MOV EAX, 42 можно повторно использовать.

Эта оптимизация не так важна для 8 и 16 бит операционных систем (потому что они меньше), и изменение правил там также сломает старый код.