c++ 基础知识(五) 函数调用栈

1、首先我们来弄清楚栈是什么?

栈:简单来说,栈就是一个先进后出的数据结构,这个和函数的调用过程一样,调用时,调用函数在前,被调用函数在后,返回时,被调用函数先返回,调用函数在后。

正好符合先进后出的结构。我们先来看看栈的push,和pop操作。比如往栈中压入一个元素,如下图:(左边为压入之前的图,压入之后则为右边的部分)

那如果弹出来呢

这样我们可以清楚看到栈的Push和pop操作。

 2、栈帧是什么呢?

其实栈帧本质上也是一种栈,它专门保存函数掉用的各种信息比如变量,返回地址,参数等等。

如下图:

从上图我们可以看出:

1、栈的地址是向下生长的,也就是说栈低的地址比栈顶的高。

2、 一般来说,我们将%ebp到%esp这块区域叫做栈帧,每次掉用函数都会产生一个新的栈帧。

我们分两步来讲:

1、在被调用函数取得控制权之前的情况:

在被调用函数取得控制权之前,调用函数做了2件事情:1、将需要传入被调用函数的实际参数压入栈中,参数按照从右往左的方向依次压入。2、将返回地址压入栈中。

然后main函数用call指令调用子函数,EIP指令寄存器的内容被压入栈中,因为EIP寄存器是指向main中的下一条指令,所以现在返回地址就在栈顶了。在call指令执行完之后,下一个执行周期将从名为foo的标记处开始,进入了被调函数。

2、进入被调用函数的情况。

被调用函数做了几件事:

1、将调用函数的ebp压入栈(便于调用完成后找到调用函数的继续运行的位置),此时%esp指向它。

2、将esp赋值给ebp,这是ebp就有了新的值。它就是被调用函数的栈底。

3、此时就可以开辟新的空间了用move或者sub就可以了。

3、函数的返回。

当函数调用完毕的时候呢,将esp移到ebp处,然后将栈内的旧的ebp的值取出来放到ebp中,则就恢复到函数调用前的状态了。

经验分享 程序员 微信小程序 职场和发展