0

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);
 }

get 和 puts 只是函数调用,您可以不理会它们。

其汇编代码如下:(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 个字节呢?因为 20+4+4 = 28 不是 16 字节的倍数。

4

1 回答 1

3

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

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

它的总高度为 32 个字节。

于 2013-03-10T05:13:01.397 回答