首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么32位寄存器上的x86-64指令将整个64位寄存器的高位部分置零?

为什么32位寄存器上的x86-64指令将整个64位寄存器的高位部分置零?
EN

Stack Overflow用户
提问于 2012-06-24 19:40:16
回答 4查看 35.6K关注 0票数 153

x86-64 Tour of Intel Manuals中,我读到

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

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

在目标通用register.

  • 32-bit操作数中,64位操作数生成64位结果,在目标通用register.

  • 8-bit中,
  • 操作数生成32位结果,而16位操作数则生成8位或16位结果。目的通用寄存器的高56位或48位(分别)不会被该操作修改。如果8位或16位操作的结果用于64位地址计算,请显式对寄存器进行符号扩展,使其达到完整的64位。

在x86-32和x86-64汇编中,16位指令,如

代码语言:javascript
复制
mov ax, bx

不要表现出这种“奇怪”的行为,即eax的上一个单词被归零。

因此:引入这种行为的原因是什么?乍一看,这似乎不合逻辑(但原因可能是我习惯了x86-32汇编的怪癖)。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-06-24 19:53:08

我不是AMD,也不是他们的代言人,但我也会以同样的方式去做。因为将上半部分置零不会创建对前一个值的依赖关系,所以CPU必须等待。如果不这样做,register renaming机制基本上就会失败。

这样,您就可以在64位模式下使用32位值编写快速代码,而不必总是显式地破坏依赖关系。如果没有这种行为,64位模式中的每一条32位指令都必须等待之前发生的事情,即使高位部分几乎永远不会被使用。(将int设为64位会浪费缓存空间和内存带宽;x86-64 most efficiently supports 32 and 64-bit operand sizes)

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

有关实际CPU如何处理对8位和16位部分寄存器的写入(以及后续读取完整寄存器)的实际详细信息,请参阅Why doesn't GCC use partial registers?

票数 117
EN

Stack Overflow用户

发布于 2012-06-24 19:50:14

它只是节省了指令和指令集的空间。您可以使用现有的(32位)指令将较小的立即值移动到64位寄存器。

MOV EAX, 42可以重用时,它还使您不必为MOV RAX, 42编码8字节值。

这种优化对于8位和16位op并不重要(因为它们较小),而且更改规则也会破坏旧代码。

票数 12
EN

Stack Overflow用户

发布于 2020-04-01 03:20:09

如果不将零扩展到64位,这将意味着从rax读取的指令将对其rax操作数(写入eax的指令和之前写入rax的指令)具有两个依赖项,这将导致partial register stall,当有3个可能的宽度时,这将开始变得棘手,因此它有助于raxeax写入完整寄存器,这意味着64位指令集不会引入任何新的部分重命名层。

代码语言:javascript
复制
mov rdx, 1
mov rax, 6
imul rax, rdx
mov rbx, rax
mov eax, 7 //retires before add rax, 6
mov rdx, rax // has to wait for both imul rax, rdx and mov eax, 7 to finish before dispatch to the execution units, even though the higher order bits are identical anyway

非零扩展的唯一好处是确保包含rax的高位,例如,如果最初包含0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff通过保证它总是被零扩展到64位,编译器可以在mov rdx, rax中使用这个公理,而rax只需要等待它的单个依赖项,这意味着它可以更快地开始执行和退出,从而释放执行单元。此外,它还允许更有效的零习惯用法,如xor eax, eax to zero rax,而不需要REX字节。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11177137

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档