"mov (%rax),%eax" 和 "mov %rax,%eax" 有什么区别?这涉及到IT技术。

5
< p > mov (%rax),%eaxmov %rax,%eax有什么区别?我相信这是一个简单的问题,但我无法找到答案。

以下是引发我的问题的原始代码:

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

4
mov (%rax),%eax 从内存中获取值,而 mov %rax,%eax 因操作数大小不匹配而无效。但如果它有效,它只会将一个寄存器的值传输到另一个寄存器。 - Jester
1个回答

12
在 AT&T 语法中,指令为:
mov (%rax), %eax                  # AT&T syntax
或者,等价于Intel语法中的:
mov eax, DWORD PTR [rax]          ; Intel syntax

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

由于要解引用的内存地址存储在rax中,因此它可以是64位地址,在64位操作系统上运行时必需。

然而,被该内存地址指向的数据仅为32位大小,因此可以存储在32位的eax寄存器中。

请注意,此指令将隐式清零rax寄存器的上32位,以便低32位半部分(称为eax)包含加载的数据,上32位半部分为空。

AT&T语法中的括号(或Intel语法中的方括号)是您的线索,表明此指令将寄存器内容视为指针。
这就是它与其他指令的区别所在:

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寄存器中。当然,这是不可能的。缩小转换是不允许的,因此它不会汇编。

如果你真的想这样做,你必须决定要丢弃64位rax中哪一半的值。如果你决定扔掉上半部分并只复制下半部分到eax,你不需要做任何事情-直接使用eax即可。然而,如果你想扔掉下半部分并只使用上半部分,你首先要进行右移32位。


请注意,这是一个相当简单的通用参考问题。您可以在任何一本x86汇编语言的书中查找答案,并且教程应该已经教授了括号/方括号语法的重要性。有关教程和其他通用参考信息,请参见标签wiki。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接