来一起聊聊栈帧吧!!!
今天我们一起来探讨探讨栈帧。那么,首先呢,我们先想一下为什么要讨论栈帧呢?我想大家应该听说过不少次,函数调用时,变量具有临时性。那么这个所谓的临时性怎么体现出来呢?那么心里揣着这个疑问,由我们接下来慢慢讨论!
1. 讨论前的准备工作:
32位cpu通用寄存器:EAX,EBX,ECX,EDX,EBP,ESP,ESI,EDI(可用于传送和暂存数据)
EBP:指向栈帧的底部
ESP:指向栈帧的顶部
PC程序计数器:EIP(当前正在执行的下一条指令的地址)
栈帧的特点:先进后出(就如同一条只有一辆车宽的车道,第一辆车从车道入口开进去就放在了最里边, 它想出来就 必须等后面的车从车道入口出去之后才能出去)
栈帧操作:push:把一个新值压入到栈帧顶部,。(把车从车道入口开进去)
pop: 把一个栈里的值移出去。(把车从车道入口开出去)
现在我们有了初步的知识储备,那现在就让我们一起来捋一捋函数调用时的大致过程。那么现在看看下面的函数:
#include<stdio.h>
#include<windows.h>
int Add(int a, int b){
int ret = a + b;
return ret;
}
int main(){
int a = 10;
int b = 20;
int c = Add(a, b);
printf("%d", c);
system("pause");
return 0;
}
上面是一个简单的调用Add函数的简单的代码
2.探讨函数调用过程:
(1)想象出一个栈空间;
(2)调出代码的汇编语言,根据汇编语言进行行动;
经上述便利之后,我们想象中的栈帧结构图大致为:
此时函数即将开始调用:
此时栈帧空间里已经形成了形参实例化的a和b:
之后跳转至Add函数:
此时的Add函数的栈帧就开辟出来,并且对a和b做了一些列的运算操作:
现在就是函数返回的过程:
此时ebp已经指回main函数的栈底:
\
然而此时Eip中存放的是下一条指令的地址(002c1449):
此时,可以看看esp,ebp,各自的指向(注意这个函数中说的加多少都是加其类型的大小):
3:总结:
(1)函数调用时会形成栈帧结构;
(2)在函数调用完毕之后数据就失效了(注意不是清零),这也就是临时性的体现;
(3)栈帧的结构是自上向下的走向;
好了,这也是我半桶水的理解,希望你们有好的见解评论给我。
不说了,打代码去了(别问代码是谁)!!!!!