首页 文章

为什么32位寄存器上的x86-64指令归零整个64位寄存器的上半部分?

提问于
浏览
89

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

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

同一来源引用的英特尔文档(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汇编的怪癖) .

2 回答

  • 8

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

    MOV EAX, 42 可以重复使用时,它还可以避免为 MOV RAX, 42 编码8字节值 .

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

  • 73

    我不是AMD或为他们说话,但我会以同样的方式做到这一点 . 因为将高半部分归零不会对先前的值产生依赖性,所以cpu必须等待 . 如果没有这样做,寄存器重命名机制基本上会被打败 . 这样,您就可以在64位模式下编写快速32位代码,而无需始终明确地断开依赖关系 . 如果没有这种行为,64位模式下的每个32位指令都必须等待之前发生的事情,即使这个高部分几乎不会被使用 .

    16位指令的行为很奇怪 . 依赖性疯狂是现在避免16位指令的原因之一 .

相关问题