为了探究函数创建与销毁在内存里的变化,做以下文章,个人理解
- 首先了解寄存器
寄存器有:eax ebx ecx edx ebp esp
这里我们只需要关系ebp与esp寄存器
这两个寄存器是用来存放地址的 ,而存放的两个地址用来维护函数栈帧的;
这里我们要知道main函数也是被其他函数调用
mainCRTStartup调用__tmainCRTStartup函数
而__tmainCRTStartup调用main函数才开始工作
程序流程
先写流程所需代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 10;
int b = 20;
int c = 0;
c = add(a, b);
printf("%d\n",c);
return 0;
}
首先编译器自动在内存开辟一块空间为__tmainCRTStartup函数使用。
ebp指向栈底
esp指向栈顶
首先知道开辟空间为从高地址向低地址开辟
main函数的空间创建
先将ebp的地址压栈在tmain..
ps:压栈也会让esp向低地址移动4个地址
然后在将esp的地址赋给ebp,将esp与ebp内地址相同
然后esp得到一个更低的地址,然后esp到ebp就是main函数所开辟的栈帧
在eax esi edi依次压栈
edi为ebp偏移的距离也是函数的栈帧空间
ecx为0x39次数
eax为一个16进制值
最后的rep stos步骤是将每四个字节放入eax内的值,放0x39次;
初始化main栈帧内的值
现在才开始走main函数内的代码汇编;
变量a b c分别以ebp为参考偏移几个字节保存在所开辟的栈帧内
为准备进入add函数准备
将a,b以ebp偏移的地址内的数据存入2个其他的寄存器通过寄存器压栈在main栈帧上
call指令为转入函数 在传入函数前会先将call下一汇编地址压栈在main栈帧上
然后再将ebp在main函数栈帧的底传给一个寄存器然后压栈(为了保存main的栈底)如准备创建main函数栈帧前保存tmain..的栈底。
进入add函数:
如开辟main函数栈帧一样,开辟add函数的栈帧空间,初始化内部参数
在函数add栈帧内创建一个变量z的空间
在函数内计算,汇编代码如下
z = x + y;
00FA187C 8B 45 08 mov eax,dword ptr [ebp+8]
00FA187F 03 45 0C add eax,dword ptr [ebp+0Ch]
00FA1882 89 45 F8 mov dword ptr [ebp-8],eax
为函数代码
为将ebp偏移+8个字节的数据保存在eax寄存器中
add为将后一个寄存器中地址值加到前一个寄存器中地址值,将ebp偏移+0xc中的值加上eax寄存器中原先保存的值最后相加保存在eax。
将eax寄存器中地址内的值传给ebp偏移-8的地址中保存----这是变量z的空间.
return z;
00FA1885 8B 45 F8 mov eax,dword ptr [ebp-8]
函数代码
将ebp偏移-8的的地址的值(z的值)拷贝到eax
接下来是add函数的销栈
00FA1888 5F pop edi
00FA1889 5E pop esi
00FA188A 5B pop ebx
1.2.3.这三条代码将栈顶的三行代码块出栈,出栈后数据保存在edi esi ebx 寄存器中,
esp向下加0x0c的地址(向高地址移动)
接下来将esp指向ebp保存的地址
00FA189A 5D pop ebp
00FA189B C3 ret
1.将保存main-ebp值的地址出栈,出栈的数据保存在ebp中,覆盖ebp原先保存的地址
2.ret然后结束add函数的调用,并且保存的main函数汇编地址的下一条指令生效,009418f7内容出栈
esp+0x4,函数销毁完毕;
add传回值的接收
首先将esp偏移+0x8地址--将形参x,y出栈
00FA18F7 83 C4 08 add esp,8
然后再将eax中的值拷贝到ebp偏移量-0x20处
00FA18FA 89 45 E0 mov dword ptr [ebp-20h],eax
此刻函数的调用结束,返回函数成功
这里有几个点要注意 esp ebp eax等等是寄存器不会因为函数的销毁而销毁
在函数的创建与销栈过程就是将开辟空间然后重新赋值,覆盖掉原先的值,不论曾经是否被调用过
函数的空间开辟,压栈都是高地址到低地址的,所以压栈都是地址偏移负数 出栈都是正数
为了分别看到我将bit鹏哥的截图拿来使用,仅供参考函数栈帧的创建.png · 比特鹏哥/class108 - Gitee.com