编辑真正的问题是在帖子的末尾, 我试图理解 gcc 如何管理堆栈大小,但我有一些问题我找不到答案。
当我在另一个函数中调用一个函数时,Gcc 会做一些奇怪的事情。它分配额外的字节,我不明白为什么。
这是有史以来最简单的 C 代码:
int f(){
int i =12;
return 0;
}
int main(void){
f();
return 0;
}
然后是 gdb 产生的 f() 的 disass :
0x08048386 <+0>: push %ebp
0x08048387 <+1>: mov %esp,%ebp
0x08048389 <+3>: sub $0x10,%esp <- this part
0x0804838c <+6>: movl $0xc,-0x4(%ebp)
0x08048393 <+13>: mov $0x0,%eax
0x08048398 <+18>: leave
0x08048399 <+19>: ret
好吧,我不明白。gcc 使 16 字节对齐堆栈,因为 i 是一个 int(所以 4 个字节) gcc 在堆栈上为 i 分配 16 个字节。
但是一旦我在 f() 中调用一个函数,我就不知道 gcc 在做什么。这是新的 C 代码:
int g(int i){
i=12;
return i;
}
int f(){
int i =12;
g(i);
return 0;
}
int main(void){
f();
return 0;
}
然后 f() disass :
0x08048386 <+0>: push %ebp
0x08048387 <+1>: mov %esp,%ebp
0x08048389 <+3>: sub $0x14,%esp <- Here is my understanding
0x0804838c <+6>: movl $0xc,-0x4(%ebp)
0x08048393 <+13>: mov -0x4(%ebp),%eax
0x08048396 <+16>: mov %eax,(%esp)
0x08048399 <+19>: call 0x8048374 <g>
0x0804839e <+24>: mov $0x0,%eax
0x080483a3 <+29>: leave
0x080483a4 <+30>: ret
然后 gcc 分配了 4 个额外的字节,而 f() 调用 g() 时没有更多的变化。
当我使用更多功能时,这可能是最糟糕的。
所以你们中的任何人都知道这个额外的字节是什么以及 gcc 的堆栈分配策略是什么?
先感谢您。
编辑:真正的问题
好的抱歉我写的问题太快了事实上 sub 0x14 %esp 我真正理解的是这段代码:
int f(){
char i[5];
char j[5];
i[4]=0;
j[4]=0;
strcpy(i,j);
return 0;
}
int main(void){
f();
return 0;
}
然后 f() 的 disass :
0x080483a4 <+0>: push %ebp
0x080483a5 <+1>: mov %esp,%ebp
0x080483a7 <+3>: sub $0x28,%esp
0x080483aa <+6>: movb $0x0,-0x9(%ebp)
0x080483ae <+10>: movb $0x0,-0xe(%ebp)
0x080483b2 <+14>: lea -0x12(%ebp),%eax
0x080483b5 <+17>: mov %eax,0x4(%esp)
0x080483b9 <+21>: lea -0xd(%ebp),%eax
0x080483bc <+24>: mov %eax,(%esp)
0x080483bf <+27>: call 0x80482d8 <strcpy@plt>
0x080483c4 <+32>: mov $0x0,%eax
0x080483c9 <+37>: leave
0x080483ca <+38>: ret
堆栈看起来像这样:
[oldip][oldebp][Extra(8B)][Arrays(10B)][重新排列堆栈(14B)][Argument1(4B)][Argument2(4B)]
在这里,我们看到保存的 ebp 和局部变量之间有 8 个额外的字节。所以这真的是我的理解。
很抱歉发布得太快,仍然感谢您的快速回答。