2013-03-09 87 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字节。