“mov(%rax),%eax”和“mov%rax,%eax”之间的区别是什么?

时间:2016-12-19 22:55:17

标签: assembly x86 x86-64 cpu-registers

mov -0x8(%rbp),%rax mov (%rax),%eax lea (%rax,%rax,1),%edx mov -0x8(%rbp),%rax mov %edx,(%rax) mov -0x8(%rbp),%rax mov (%rax),%eax TimeoutException之间有什么区别?我确信这是一个简单的问题,但我无法在任何地方找到答案。

以下是提示我问题的原始代码:

CancellationException

1 个答案:

答案 0 :(得分:3)

在AT& T语法中,指令:

mov (%rax), %eax                  # AT&T syntax

或等效于英特尔语法:

mov eax, DWORD PTR [rax]          ; Intel syntax

解除引用存储在rax中的内存地址,从该内存地址读取一个32位值,并将其存储在eax寄存器中。

因为被解除引用的内存地址存储在rax中,所以它可以是64位地址,这在64位操作系统上运行时是必需的。

但是,该存储器地址指向的数据只有32位,因此可以存储在32位eax寄存器中。

注意,该指令将隐含地将rax寄存器的高32位置零,以便较低的32位半(称为eax)将包含已加载的数据,而高32位 - 一半将是空的。

AT& T语法中的括号(或英特尔语法中的方括号)是您的线索,该指令将寄存器的内容视为指针。
这就是它的不同之处,例如:

mov %rcx, %rax                    # AT&T syntax
mov rax, rcx                      ; Intel syntax

这只是将rcx寄存器的内容复制到rax寄存器中。没有解除引用。寄存器中的值直接作用。

请注意,上述示例与您问题中的另一个示例类似

mov %rax, %eax                    # AT&T syntax (INVALID!)
mov eax, rax                      ; Intel syntax (INVALID!)

但不完全相同。最后一种情况实际上是无效指令,因为存在操作数大小不匹配。如果它有效,则指令将64位rax寄存器的内容复制到32位eax寄存器中。当然,这是不可能的。不允许缩小转换次数,因此不会组合。

如果确实想要这样做,则必须决定rax中要丢弃的64位值的哪一半。如果您决定丢弃高位并仅将低位复制到eax,则无需执行任何操作 - 只需直接使用eax即可。但是,如果你想丢掉低位并只使用高位,你首先要做一个右移32位。

请注意,这是一个相当简单的一般参考问题。您可以在任何有关x86汇编语言的书中查找答案,教程应该教您关于括号/括号语法的重要性。有关一些教程和其他一般参考信息,请参阅标记wiki。