mov%edi和mov%rsi的说明是什么?

时间:2015-07-14 11:22:04

标签: c gas disassembly

我编写了一个定义整数变量x的基本C程序,将其设置为零并返回该变量的值:

|

当我使用objdump(使用gcc在Linux X86-64上编译)转储目标代码时:

#include <stdio.h>

int main(int argc, char **argv) {
    int x;
    x = 0;
    return x;
}

我可以看到函数序言,但在我们在地址0x0000000000400474 <main+0>: push %rbp 0x0000000000400475 <main+1>: mov %rsp,%rbp 0x0000000000400478 <main+4>: mov %edi,-0x14(%rbp) 0x000000000040047b <main+7>: mov %rsi,-0x20(%rbp) 0x000000000040047f <main+11>: movl $0x0,-0x4(%rbp) 0x0000000000400486 <main+18>: mov -0x4(%rbp),%eax 0x0000000000400489 <main+21>: leaveq 0x000000000040048a <main+22>: retq 处将x设置为0之前,有两条指令将%edi和%rsi移动到堆栈上。这些是为了什么?

此外,与将x设置为0的情况不同,GAS语法中显示的mov指令没有后缀。

  

如果未指定后缀,并且指令没有存储器操作数,则GAS根据目标寄存器操作数的大小推断操作数大小。

在这种情况下,0x000000000040047f-0x14(%rsbp)都是内存操作数,它们的大小是多少?由于%edi是32位寄存器,32位移到-0x20(%rbp),而由于%rsi是64位寄存器,64位移到-0x14(%rsbp)

2 个答案:

答案 0 :(得分:9)

在这个简单的例子中,为什么不直接问你的编译器?对于GCC,clang和ICC,有-fverbose-asm选项。

main:
    pushq   %rbp    #
    movq    %rsp, %rbp  #,
    movl    %edi, -20(%rbp) # argc, argc
    movq    %rsi, -32(%rbp) # argv, argv
    movl    $0, -4(%rbp)    #, x
    movl    -4(%rbp), %eax  # x, D.2607
    popq    %rbp    #
    ret

所以,是的,他们通过使用“旧”帧指针方法将argvargv保存到堆栈中,因为新架构允许直接从堆栈指针中减去/添加,因此省略了帧指针(-fomit-frame-pointer)。

答案 1 :(得分:0)

Purpose of ESI & EDI registers?

基于此和上下文,我不是专家,但我猜这些是捕获main()输入参数。 EDI采用标准宽度,与int argc匹配,而RSI采用长,与char **argv指针匹配。