【发布时间】:2015-10-03 00:07:42
【问题描述】:
我编写了一个基本的 C 程序,它定义了一个整数变量 x,将其设置为零并返回该变量的值:
#include <stdio.h>
int main(int argc, char **argv) {
int x;
x = 0;
return x;
}
当我使用 objdump(使用 gcc 在 Linux X86-64 上编译)转储目标代码时:
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
我可以看到函数序言,但是在我们将地址 0x000000000040047f 处的 x 设置为 0 之前,有两条指令将 %edi 和 %rsi 移动到堆栈上。这些是干什么用的?
此外,与我们将 x 设置为 0 不同的是,GAS 语法中所示的 mov 指令没有后缀。
如果没有指定后缀,并且指令没有内存操作数,GAS 会根据目标寄存器操作数的大小推断操作数大小。
在这种情况下,-0x14(%rsbp) 和 -0x20(%rbp) 是否都是内存操作数,它们的大小是多少?由于 %edi 是一个 32 位寄存器,是否将 32 位移动到 -0x14(%rsbp) 而由于 %rsi 是一个 64 位寄存器,所以将 64 位移动到 %rsi,-0x20(%rbp)?
【问题讨论】:
-
在这两个mov之后
%rsi是argv和%edi是argc。 -
有趣!据我了解,参数(即 argc 和 argv)在堆栈帧之前被推入堆栈(即 push %rbp)。这是否意味着 argc 和 argv 在 main 的堆栈框架内?
-
其实我可能错了。编写另一个只调用您的
main函数的小函数,然后再次 objdump 文件,您将看到。 -
@GeorgeRobinson 在 x86_64 中有一个非常常用的调用约定,其中前 6 个参数被放入寄存器。 en.wikipedia.org/wiki/…
标签: c gnu-assembler disassembly