2010-11-09 69 views
0

编辑真正的问题是在帖子的末尾 我想展现gcc如何管理堆栈大小,但我有一些问题,我没有找到答案。gcc用我的堆栈做什么?

当我在另一个函数中调用函数时,Gcc会做些奇怪的事情。它分配额外的字节,我不明白为什么。

这里是simpliest C代码以往:

int f(){ 
    int i =12; 
    return 0; 
} 


int main(void){ 
    f(); 
    return 0; 
} 

,然后f的disass()的GDB生产:

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为堆栈分配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更多变化() 是主叫克()。

当我玩更多的功能时,这可能是最糟糕的。

所以你们有什么想法是什么额外的字节和什么是海湾合作委员会的 堆栈分配政策?

预先感谢您。

编辑:真正的问题

好抱歉,我写的问题其实太快它的确定与 子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 <[email protected]> 
0x080483c4 <+32>: mov $0x0,%eax 
0x080483c9 <+37>: leave 
0x080483ca <+38>: ret 

堆栈看起来像这样的事情:

[oldip] [oldebp] [额外(8B)] [阵列(10B)] [重新排列堆(14B)] [ARGUMENT1(4B)] [ARGUMENT2(4B)]

这里我们看到,8额外的字节在保存的ebp和局部变量之间。所以这里是我的理解。

对不起,张贴太快,仍然感谢您的快速 答案。

+1

f在两个代码清单中的定义完全相同。你的意思是在第一个代码中加入一些不同的代码吗? – Heatsink 2010-11-09 03:19:07

+1

收集您丢弃的返回值? – 2010-11-09 03:19:33

回答

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个字节包括我和栈对齐,加上一个参数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 
0

我想在第一种情况下,4个字节是调用g()时所需的一个参数。而在第二种情况下,在调用strcpy()时,两个参数需要两个4字节的字。用三个参数调用一个虚拟函数,看它是否改变为12个字节。

+0

我不这么认为,因为参数存储在两个数组之后,然后8个字节的额外数字在这个数组之前:[oldeip] [oldebp] [Dummy 8bytes] [array(16bytes)] [Dummy 8bytes] [8bits )] – poulecaca 2010-11-09 07:58:30

+0

嗯,好吧,只是一个理论 – 2010-11-09 16:22:04