2

谁能向我解释为什么以下代码行 int main (int argc, char *argv[])

{
int i=17;
int output=0

.....

}

被翻译成以下 x64 汇编代码:

pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
movl %edi, -20(%rbp)
movq %rsi,-32(%rbp)
movl $17, -8(%rbp)
movl $0, -4(%rbp)
...

我不明白为什么 SP 减少了 32。寄存器 %edi、%rsi 似乎对应于主代码中未使用的 argc 和 *argv[]。我认为 [%esp, %rbp] 之间的空间仅分配给局部变量而不是函数 args,因此在上面的代码中大小应该只有 8,即 rsp 应该减少 8 而不是 32。有什么解释吗?

4

1 回答 1

0

知道 ... 部分会有所帮助。

我假设 gcc 决定 ... 部分需要寄存器,因此它将变量推入堆栈。

堆栈可用于任何局部变量或函数参数。SysV x64 ABI 的唯一要求是前几个函数参数从寄存器开始。

然后,该函数可以将参数移到堆栈上,并根据需要将局部变量带入寄存器,这取决于编译器!

不保证将本地变量放入堆栈!args 也不会留在寄存器中。

所以它推动了 argc 和 argv,然后它决定推动 i 和输出。那是 24 字节的空间。但是如果接下来是函数调用,则堆栈必须对齐到 16 个字节,因此达到 32 个字节。

试试 -O3 看看代码是否有变化。

换一种方式:

参数如下: %rdi %rsi %rdx %rcx %rbx %r8 %r9(堆栈上的额外参数)(红色区域)

是函数的开始。然后该函数可以对堆栈做任何它想做的事情。是的,随便!只要它以它进入的状态返回堆栈。

(注意,这是针对系统 V(除 windows 外的所有设备都使用),windows 不同)

于 2013-02-23T20:55:42.897 回答