首页 > 代码库 > 函数调用时的帧变化

函数调用时的帧变化

【原文】

  函数调用另一个词语表示叫作过程。一个函数调用包括将数据和控制从代码的一部分传递到另一部分。另外,它还必须在进入时为函数的局部变量分配空间,并在退出时释放这些空间。而数据传递,局部变量的分配和释放是通过操纵程序栈来实现的。

  我们先来了解一个概念,栈帧。机器用栈来传递过程参数,存储返回信息等。为单个过程(函数调用)分配的那部分栈成为栈帧。栈帧其实是两个指针寄存器:寄存器%ebp为帧指针,寄存器%esp为栈指针。当程序运行时,栈指针可以移动,大多数的下线访问都是通过帧指针进行的。总之简单一句话,栈帧的主要作用是用来控制盒保存一个过程的所有信息的。栈帧结构如下所示:

 

  下面用一个程序为例进行简要说明函数调用的基本过程:

int swap_add(int* xp,int* yp) {    int x = *xp;    int y = *yp;    *xp = y;    *yp = x;    return x+y;}int caller(){    int arg1 = 534;    int arg2 = 1057;    int sum = swap_add(&arg1,&arg2);    int diff = arg1 - arg2;        return sum * diff;}

  经过汇编之后caller部分的代码如下:

caller:    pushl %ebp   //保存%ebp    movl %esp,%ebp    //设置新的帧指针为旧的栈指针    subl $24,%esp  //分配24子节的栈空间    movl $534,-4(%ebp) //设置arg1=534    movl $1057,-8(%ebp) //设置arg2=1057    leal -8(%ebp),%eax //计算&arg2    movl %eax,4(%esp) //将&arg2存入栈中    leal -4(%ebp),%eax //计算&arg1    movl %eax,(%esp) //将&arg1存入栈中    call swap_add //调用swap_add