关于堆栈帧的对齐,来自CSAPP的一个例子

时间:2013-03-09 15:25:23

标签: c assembly compiler-construction x86

IA32遵循以下惯例:确保每个堆栈帧都是16字节长的倍数。这是一个示例函数:

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

获取和放置只是函数调用,你可以不管它们。

汇编代码如下:( 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字节的倍数。

1 个答案:

答案 0 :(得分:2)

不要忘记堆栈顶部的返回地址! call在跳转到目标之前将当前pc推入堆栈,ret弹出该pc并跳回到它。因此,堆栈更准确

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

,总高度为32字节。