我试图了解如何在C中调用函数。当我反汇编代码(gcc -gdb;我在Linux上使用i5-3320M)来获取函数toto
的序言时:
void nop(){return ;}
void toto(int i, int j)
{
return;
}
int main(int argc, char **argv)
{
int i = 1;
int* pt;
i = 0;
}
我得到了序幕:
0x0000000000400523 <+0>: push %rbp
0x0000000000400524 <+1>: mov %rsp,%rbp
0x0000000000400527 <+4>: sub $0x8,%rsp
这里我不明白为什么rsp
递减8,因为我没有在toto
中使用局部变量。而且,如果我使用局部变量:
void toto(int i, int j)
{
int i=1
return;
}
我得到以下序言:
0x0000000000400523 <+0>: push %rbp
0x0000000000400524 <+1>: mov %rsp,%rbp
0x0000000000400527 <+4>: sub $0x18,%rsp
在这里我不明白为什么rsp
递减0x18(24字节)。我希望有16个字节的东西,因为我已经有了8的神秘偏移量,而且我需要4个字节用于int。但我的架构是64位,堆栈中的一个字不能少于8个字节,因此8 + 8 = 16。
答案 0 :(得分:3)
The x86_64 ABI要求在输入函数时,%rsp
始终是16的倍数。因此,在 push %rbp
之后,必须减去%rsp
之类的值0x8,0x18,0x28等。
更新。对不起所有赞成这个的人,我欺骗了你。可以很容易地看出,每个push %rbp%
始终与call
或callq
配对,后者提供0x10字节,因此从%rsp
中减去的额外值必须是0x10的倍数。好。
关于您的第一个问题,您必须在没有优化的情况下进行编译。通过优化,您的所有功能都会崩溃为repz retq
。