【问题标题】:Dereferencing 64 bit register after using lower half in add [duplicate]在添加中使用下半部分后取消引用 64 位寄存器 [重复]
【发布时间】:2012-05-02 15:31:10
【问题描述】:

我有一个 64 位寄存器,其中包含一个内存地址。如果我对寄存器的下半部分执行算术运算,然后尝试取消引用它,则会出现分段错误。这是一个例子:

movsx rax, BYTE PTR [rdi]  # ok
add edi, 1 # the address is correct but....
movsx rax, BYTE PTR [rdi] # segmentation fault here

如果我在第 2 行中将 edi 更改为 rdi 它可以工作,所以我只是想知道为什么在这种情况下我不能使用 rdi 的下半部分。如果有人提供有关正确使用寄存器下部的信息的任何链接/参考,我也将不胜感激。

非常感谢您的帮助。

【问题讨论】:

    标签: assembly x86-64


    【解决方案1】:

    来自"AMD64 Architecture Programmer’s Manual Volume 1: Application Programming"

    3.1.2 64 位模式寄存器:

    一般来说,字节和字操作数存储在 GPR 的低 8 位或 16 位中,无需修改它们的 分别为高 56 位或 48 位。然而,双字操作数通常存储在低 32 位 GPR 零扩展至 64 位

    【讨论】:

    • 非常感谢您的链接。无论出于何种原因,来自 AMD 网站的链接对我不起作用,但我能够得到它here。再次感谢。
    【解决方案2】:

    当您对 edi 或任何其他 32 位下半部分寄存器执行操作时,它会自动将整个寄存器的上半部分归零。

    因此,rdi 的高 32 位将在 add edi, 1 之后为零。

    【讨论】:

    • 至于为什么会有这样的行为(而不是保持上半部分不变),我的猜测是它打破了很多错误的依赖关系并且极大地帮助了寄存器重命名。
    • 我明白了——现在说得通了。我无法弄清楚的原因是因为我使用 printf 来显示地址并使用格式说明符“%X”而不是“%lX”——所以在我看来地址是 32 而不是 64位。好吧——非常感谢您的帮助。
    • Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register? 是的,显而易见的原因是为了避免错误的依赖关系,使 32 位操作数大小变得高效(并且可以作为默认值使用)成为可能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-16
    • 1970-01-01
    • 2017-01-03
    • 2019-04-21
    • 1970-01-01
    • 1970-01-01
    • 2011-10-26
    相关资源
    最近更新 更多