Function 带有x64 sta的GCC

Function 带有x64 sta的GCC,function,gcc,assembly,stack,64-bit,Function,Gcc,Assembly,Stack,64 Bit,有人能给我解释一下为什么下面的代码行吗 int main(int argc,char*argv[]) 将转换为以下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[]相对应

有人能给我解释一下为什么下面的代码行吗 int main(int argc,char*argv[])

将转换为以下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。有什么解释吗?

知道。。。这一部分会有所帮助

我想gcc决定了。。。部分需要寄存器,因此它将变量推送到堆栈上

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

然后,该函数可以将参数移动到堆栈上,并将局部变量带到寄存器中(如果需要),这取决于编译器

本地变量不能保证放在堆栈上!arg也不会留在寄存器中

所以它推送argc和argv,然后决定推送i和输出。这是24字节的空间。但是如果下一个函数调用,那么堆栈必须对齐到16个字节,这样就变成了32个字节

试试-O3,看看代码是否正确

换言之:

Args如下所示: %rdi %rsi %黑索今 %rcx %rbx %r8 %r9 (堆栈上的额外参数) (红色区域)

是函数的开始。然后,函数可以对堆栈执行任何它想要的操作。是的,随便!只要它返回的堆栈处于它所处的状态


(注意,这是针对system V的(除windows之外的所有工具都使用),windows是不同的)

请参阅,它似乎都是编译器优化的一部分。但是,因为它仍然需要遵守调用约定(在本例中为
cdecl
),所以它们在被调用后仍然存储在堆栈中。在我看来,GCC像这样布置堆栈:[输出:4字节]-[i:4字节]-[alignment padding:12字节]-[space to home EDI:4字节]-[space to home RSI:8字节]。我猜这12个填充字节是为了将堆栈重新对齐到16字节的边界。
pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
movl %edi, -20(%rbp)
movq %rsi,-32(%rbp)
movl $17, -8(%rbp)
movl $0, -4(%rbp)
...