栈帧(函数调用)
来源:互联网 发布:2017农村淘宝 编辑:程序博客网 时间:2024/06/18 00:27
我们都知道在写一个函数时会使用形参,形参实例化时会形成一份拷贝,调用这个函数时会把实参传进去,调用完之后那些临时拷贝又被释放,那么计算机在调用函数时是如何进行形参的保存和释放的呢?又如何返回形参?我们可以通过栈帧来理解函数的调用原理。
首先,栈是从高地址向低地址延伸的。每个函数的每次调用都有它自己独立的一个栈帧,这个栈帧中有它所需要的各种信息。每个函数都有自己的一份esp和ebp,而CPU只有一份esp和ebp。因为ebp和esp永远保存最新当前函数的值,所以每个函数都有自己的esp和ebp指向栈顶和栈底。
esp:栈顶寄存器,指向栈的低地址。
ebp:栈底寄存器,指向高地址。
pc指针:指向当前运行程序指令的下一条指令。
call指令: ①保存当前指令下一条指令的地址(方便返回)
②通过jmp跳到指定函数入口地址处(fun函数)
黑色线指的是main函数.
红色线指的是被调用者fun函数.
蓝色线指的是fun函数返回时,恢复到调用之前的状态.
CPU在重复的执行三个操作:取指令、分析指令、执行指令,取指令通过pc指针,分析指令通过CPU里的各种指令集。
接下来我们看一段代码:
#include<windows.h>
#include<iostream>
using namespace std;
int fun(int x,int y)
{
intc = 0xcccccccc;
returnc;
}
int main()
{
inta = 0xaaaaaaaa;
intb = 0xbbbbbbbb;
intfir = fun(a, b);
cout<< "lucky!" << endl;
system("pause");
}
我们可以按F10进入调试,选择反汇编,请看截图
由图可看出参数实例化的时候是从右往左的
调用fun函数栈帧形成的过程:
push ebp 首先将pc指针下移然后把ebp寄存器的内容(main函数的栈底地址)
存到fun函数的当前栈顶(当前esp指向的地址);
mov ebp esp 把esp的内容赋给ebp, fun函数的栈底;
sub esp,0E4h 给esp减去一个随机值,指向一个新的fun函数栈顶;
fun函数返回时的过程:
mov esp ebp 把esp指向ebp的内容,形成新的栈顶
pop ebp 将栈顶的内容(main:ebp)弹出来放在ebp(地址空间图上的第一个把esp指针上移
ret 把main:retaddr返回给pc ,esp上移;使pc指向main函数的下一条指令
fun函数返回后a和b就会被释放esp会回到之间的位置
这就是fun函数调用的原理(不是很详细)。
欢迎大家指出来当中的错误。
- 栈帧(函数调用)
- 函数调用过程的真实情况(栈帧)
- 函数的调用过程(栈帧)
- 函数的调用过程(栈帧)
- 浅谈函数调用过程(栈帧)
- 函数的调用过程(栈帧)
- 函数的调用过程(栈帧)
- 函数的调用过程(栈帧)
- 关于函数的调用过程(栈帧)
- 小结 | 函数的调用过程(栈帧)
- 函数的调用过程(栈帧)
- 函数的调用过程(栈帧)
- 函数的调用过程(栈帧)
- 函数的调用过程(栈帧)
- C语言中的函数调用(栈帧)
- 函数调用栈(栈帧)
- 栈帧---函数调用原理
- 函数调用(续)
- RabbitMQ 入门 Helloworld
- 【iOS】基于Realm数据库的记账软件--钱包/记账模块(四)终
- 【菜鸟学框架】——struts2结合框架分析执行流程
- C语言实现HashMap
- 放播视频
- 栈帧(函数调用)
- java学习之异常
- 最长合成字串
- BZOJ4216 Pig 解题报告【卡空间】【数据结构】【分块】
- HDU 1213 How Many Tables(并查集)
- 各个语言的入口特征和区段特征
- RabbitMQ (二)工作队列
- 15个实用的PHP正则表达式
- Java 中的包装类