目录
- 1.栈帧
- 1.进程地址空间
- 2.栈帧说明
- 2.认识相关寄存器
- 3.认识相关汇编命令
- 4.过程理解
- 5.栈帧总结
- 6.补充
1.栈帧
1.进程地址空间

.进程地址空间
2.栈帧说明
- 调用函数,形成栈帧
- 函数返回,释放栈帧
- 局部变量是存放在栈区上的
- 栈区内存的使用习惯是:
- 先使用高地址空间,再使用低地址空间
- 如:数组随着下标的增长,地址是由低到高变化的
2.认识相关寄存器
eax:通用寄存器,保留临时数据,常用于返回值ebx:通用寄存器,保留临时数据ebp:栈底寄存器esp:栈顶寄存器eip:指令寄存器,保存当前指令的下一条指令的地址
3.认识相关汇编命令
mov:数据转移指令push:数据入栈,同时esp栈顶寄存器也要发生改变pop:数据弹出至指定位置,同时esp栈顶寄存器也要发生改变sub:减法命令add:加法命令call:函数调用,1. 压入返回地址 2. 转入目标函数- 将当前指令的下一条指令入栈(push到栈中,影响ESP)
- 跳转到目标函数起始地址处运行(修改EIP,到达目标函数)
jump:通过修改eip,转入目标函数,进行调用ret:恢复返回地址,压入eip,类似pop eip命令
4.过程理解
-
起步,
main()也是要被调用的

-
main()也要形成栈帧结构

-
起步

-
开始调用
-
调用
call前

-
调用
call后

-
整体图解

-
-
形成栈帧

-
释放栈帧

-
释放临时拷贝,彻底释放空间

5.栈帧总结
- 调用函数,需要先形成临时拷贝,形成过程是从右向左的
- 临时空间的开辟,是在对应函数栈帧内部开辟的
- 函数调用完毕,栈帧结构被释放掉
- 临时变量具有临时性的本质:栈帧具有临时性
- 调用函数是有成本的,成本体现在时间和空间上,本质是形成和释放栈帧有成本
- 函数调用,因拷贝所形成的临时变量,变量和变量之间的位置关系是有规律的(地址连续)
6.补充
- 堆上都是动态分配,做不到静态分配
- 栈既可以静态分配,也可以动态分配
- 静态分配 – 在函数体中创建了一个变量
- 动态分配
- 头文件
<malloc.h>下,有一个void* __cdecl alloca(size_t) - 作用与malloc等类似,但是它申请的是“栈(stack)”空间的内存
- 用完会在退出栈时自动释放,无需手动释放
- 头文件