为什么32位寄存器上的x86-64指令将整个64位寄存器的高位归零? [英] Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?

查看:322
本文介绍了为什么32位寄存器上的x86-64指令将整个64位寄存器的高位归零?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

x86-64英特尔手册中浏览 ,我读了

也许最令人惊讶的事实是,诸如MOV EAX, EBX之类的指令会自动将RAX寄存器的高32位清零.

Perhaps the most surprising fact is that an instruction such as MOV EAX, EBX automatically zeroes upper 32 bits of RAX register.

同一来源引用的英特尔文档(手动基本体系结构中的3.4.1.1通用寄存器在64位模式下)告诉我们:

The Intel documentation (3.4.1.1 General-Purpose Registers in 64-Bit Mode in manual Basic Architecture) quoted at the same source tells us:

  • 64位操作数在目标通用寄存器中生成64位结果.
  • 32位操作数在目标通用寄存器中生成32位结果,将其零扩展为64位结果.
  • 8位和16位操作数生成8位或16位结果.目的通用寄存器的高56位或高48位(分别)不会被该操作修改.如果将8位或16位运算的结果用于64位地址计算,则将寄存器显式符号扩展为完整的64位.
  • 64-bit operands generate a 64-bit result in the destination general-purpose register.
  • 32-bit operands generate a 32-bit result, zero-extended to a 64-bit result in the destination general-purpose register.
  • 8-bit and 16-bit operands generate an 8-bit or 16-bit result. The upper 56 bits or 48 bits (respectively) of the destination general-purpose register are not be modified by the operation. If the result of an 8-bit or 16-bit operation is intended for 64-bit address calculation, explicitly sign-extend the register to the full 64-bits.

在x86-32和x86-64组件中,有16位指令,例如

In x86-32 and x86-64 assembly, 16 bit instructions such as

mov ax, bx

不要显示eax的高位字为零的这种奇怪"行为.

don't show this kind of "strange" behaviour that the upper word of eax is zeroed.

因此:引入此行为的原因是什么?乍一看似乎是不合逻辑的(但是原因可能是我已经习惯了x86-32程序的怪癖).

Thus: what is the reason why this behaviour was introduced? At a first glance it seems illogical (but the reason might be that I am used to the quirks of x86-32 assembly).

推荐答案

我不是AMD也不代表他们说话,但是我会以相同的方式做到这一点.因为将高半数置零不会对先前的值产生依赖性,所以CPU必须等待.如果不采用这种方法,寄存器重命名机制将基本失效.

I'm not AMD or speaking for them, but I would have done it the same way. Because zeroing the high half doesn't create a dependency on the previous value, that the CPU would have to wait on. The register renaming mechanism would essentially be defeated if it wasn't done that way.

这样,您可以在64位模式下使用32位值编写快速代码,而不必始终显式破坏依赖关系.如果没有这种行为,那么即使64位模式下的每条32位指令几乎都不会被使用,也将不得不等待之前发生的事情. (将int设置为64位会浪费缓存占用空间和内存带宽;

This way you can write fast code using 32-bit values in 64-bit mode without having to explicitly break dependencies all the time. Without this behaviour, every single 32-bit instruction in 64-bit mode would have to wait on something that happened before, even though that high part would almost never be used. (Making int 64-bit would waste cache footprint and memory bandwidth; x86-64 most efficiently supports 32 and 64-bit operand sizes)

8位和16位操作数大小的行为很奇怪.依赖疯狂是现在避免使用16位指令的原因之一. x86-64从8086的8位和386的16位继承了这一点,并决定让8位和16位寄存器在64位模式下的工作方式与在32位模式下的工作方式相同.

The behaviour for 8 and 16-bit operand sizes is the strange one. The dependency madness is one of the reasons that 16-bit instructions are avoided now. x86-64 inherited this from 8086 for 8-bit and 386 for 16-bit, and decided to have 8 and 16-bit registers work the same way in 64-bit mode as they do in 32-bit mode.

另请参见为什么GCC不使用部分寄存器?实际CPU如何处理对8位和16位部分寄存器的写入(以及随后对全寄存器的读取)的详细信息.

See also Why doesn't GCC use partial registers? for practical details of how writes to 8 and 16-bit partial registers (and subsequent reads of the full register) are handled by real CPUs.

这篇关于为什么32位寄存器上的x86-64指令将整个64位寄存器的高位归零?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆