2010-11-09 57 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