编辑真正的问题是在帖子的最后 我试图解决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字节的对齐堆栈 一个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()的暗示:
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)] [Rearrange stack(14B)] [Argument1(4B)] [Argument2(4B)]
在这里,我们看到在保存的ebp和。之间有8个额外的字节 局部变量。所以这是我的理解。
对于张贴太快而感到抱歉,仍然感谢你的快速 答案。
答案 0 :(得分:0)
0x08048386 <+0>: push %ebp
0x08048387 <+1>: mov %esp,%ebp
0x08048389 <+3>: sub $0x14,%esp <- include 0x10 bytes for stack alignment and 4 byte for 1 parameter
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
如你所见,它分配16个字节包含i和堆栈对齐,加上4个字节用于一个参数,堆栈将如下所示。
00 7f 7c 13 --> return from call address
00 00 00 00 --> this one for parameter when call g(i) --> low address
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 0C ---> i (ignore about edian) --> high address
答案 1 :(得分:0)
我认为在第一种情况下,4个字节用于调用g()时所需的一个参数。在第二种情况下,调用strcpy()时两个参数需要两个4字节的字。用三个参数调用一个虚函数,看它是否变为12个字节。