2013-03-09 82 views
0

IA32遵循約定,確保每個堆棧幀的長度爲16個字節的倍數。下面是一個例子功能:關於堆棧幀的對齊,來自CSAPP的一個例子

char *gets(char *s); //get String 
void puts(char *s); //put string to the screen 
void echo() 
{ 
    char buf[8]; 
    gets(buf); 
    puts(buf); 
} 

的獲得期權和看跌期權只是函數調用,你可以讓他們獨立。

的這個彙編代碼是作爲follws:(FROM CSAPP [計算機系統:程序員的角度])

1 echo: 
2 pushl %ebp   //Save %ebp on stack 
3 movl %esp, %ebp 
4 pushl %ebx   //Save %ebx 
5 subl $20, %esp  //Allocate 20 bytes on stack 
6 leal -12(%ebp), %ebx //Compute buf as %ebp-12 
7 movl %ebx, (%esp)  //Store buf at top of stack 
8 call gets    //Call gets 
9 movl %ebx, (%esp)  //Store buf at top of stack 
10 call puts   //Call puts 
11 addl $20, %esp  //Deallocate stack space 
12 popl %ebx   //Restore %ebx 
13 popl %ebp   // Restore %ebp 
14 ret     //Return 

堆棧等:

________ 
| old ebp| 4 bytes 
|________| 
| ebx | 4 bytes 
|________|   ___ 
| buf[7] |   | 
|________|   | 
| ... |   | 
         | 
         | 
|________|   20 bytes 
| buf[0] |   | 
|________| ebp-12 | 
| ... |   | 
         | 
|________|   _|_ 

所以爲什麼編譯器分配20字節而不是24個字節? Beacuse 20 + 4 + 4 = 28不是16字節的倍數。

+0

是否應該考慮返回值?但回聲無效。 – zoujyjs 2013-03-09 15:25:35

+3

不,但可能是由呼叫推入回聲函數的返回地址。 – 2013-03-09 16:05:06

+0

@BoPersson正是! – zoujyjs 2013-03-10 06:10:45

回答

2

不要忘記堆棧頂部的返回地址! call在跳轉到目標之前將當前的pc推入堆棧,然後ret彈出該PC並跳回到目標。因此,堆棧更精確

saved pc 
old ebp 
ebx 
buf[7] 
... 
buf[0] 
... 

其總高度爲32字節。