相信只要是了解计算机的人都知道栈和堆以及静态存储区之类的东西。但是说到栈帧可能知道的人就不是很多了= =!(大雾)。
栈帧(stack frame),用度娘解释一下:栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。可能所有的博客都说过这个。那么我们,换一个高大上的别的出处的解释:调用堆栈(英语:Call stack,港台称“呼叫堆叠”,英文直接简称为“栈”(the stack))别称有:执行栈(execution stack)、控制栈(control stack)、运行时栈(run-time stack)与机器栈(machine stack),是计算机科学中存储有关正在运行的子程序的消息的堆栈。有时仅称“堆栈”,但堆栈中不一定仅存储子程序消息。自我认为这个解释还算通俗易懂,当然度娘那个也不难理解。以我个人的简单来讲就是计算机在操作时进行调用函数或函数相关使用时在栈上所开辟的一处空间。这篇博客我将使用函数实例来简单介绍一下栈帧。
首先我们要理解几个简单的概念,在使用栈帧时,我们会用到的。
1.栈帧栈帧,我们首先要对栈有所了解,用一句话来描述,栈是从高地址向低地址延伸的。有了这句话我们下面的一些问题就可以很好地解决。
2.esp和ebp。对计算机有所了解的人可以一眼看出这两个其实是两个寄存器,一个函数使用esp和ebp两个寄存器来划定一块范围。同样我们可以简单地理解esp和ebp为两个简单的指针。
下面我们需要举一个例子来说明栈和栈帧的, 首先,我们举一个简单的引用函数的例子来解释一下。
int fun(int a,int b)
{
return a+b;
}
int main()
{
int a=10;
int b=20;
int ret=fun(a,b);
printf("%d\n",ret);
return 0;
}
这段程序是一个简单的调用fun函数的程序。当然,这个程序我们需要关注的并不是它程序本身而是为了了解该函数在计算机中的调用过程。打开VS输入这段程序,跳到反汇编我们可以看到如下的部分.
这就是main函数的汇编部分。我们来一个一个解释一下
这里我们需要解释一下几个反汇编的语言call:1,保存PC指针的地址;2,跳转到目标函数。这一点很重要因为在main函数调用过程中我们都需要遇到它。
在call汇编之后,我们调试按F11进入Fun函数部分的汇编语
fun函数的栈帧调用情况基本上和main函数的很相似。最后的ret是返回。
这里把ebp压入栈,这是为了让函数调用完之后ebp回到main函数底部。
接着为fun函数开辟空间并找到刚才的a和b变量的拷贝,因为在返回的时候计算所以这里我们开辟空间后并不需要计算。
fun函数结束,回到主函数,释放掉刚才开辟的空间,esp移动到ebp位置,弹出刚才存放的ebp地址,ebp回到该地址,esp继续下移执行下条语句。
大致的栈帧内部的图如下。。。笔触我感觉有点坑