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字节的倍数。
答案 0 :(得分:2)
不要忘记堆栈顶部的返回地址! call
在跳转到目标之前将当前pc
推入堆栈,ret
弹出该pc并跳回到它。因此,堆栈更准确
saved pc
old ebp
ebx
buf[7]
...
buf[0]
...
,总高度为32字节。