函数的调用过程(栈帧的创建和销毁)
来源:互联网 发布:移植术后软件 编辑:程序博客网 时间:2024/06/06 18:43
为了更好地认识函数的调用过程,我们可以用反汇编代码去理解学习。
一、基本概念
1.栈帧(过程活动记录):是编译器用来实现函数调用的一种数据结构,每个栈帧对应一个未运行完的函数,栈帧中保存了该函数的返回地址和局部变量。
2.栈(stack):又名堆栈,是一种运算受限的线性表,只允许在表的一端输入输出,这一端叫栈顶,相对的另一端是栈底,遵循后进先出,栈底是高地址,栈顶是低地址,栈由内存高地址向低地址生长。
3.push: 压栈 pop:出栈
4.寄存器: 位于CPU内部,存放运行程序中的数据和指令。
ebp (栈帧的栈底指针) esp(栈帧的栈顶指针)
二、调用add函数的代码
#include <stdio.h>int add(int a, int b){int ret = 0;ret = a + b;return ret;}int main(){int a = 10;int b = 20;int ret = add(a, b);return 0;}
三、截取的部分反汇编代码,进行逐语句分析
int main(){00B81410 push ebp //在此之前,main函数在mainCRTstartup中调用,先为mainCRTsturtup开辟栈帧,有栈底,有栈顶。现在开始压栈。00B81411 mov ebp,esp //让ebp指向esp的位置。00B81413 sub esp,0E4h //esp指向[esp-oE4h]的位置,sub为减00B81419 push ebx //分别将ebx、esi、edi压栈00B8141A push esi 00B8141B push edi 00B8141C lea edi,[ebp-0E4h] //加载有效地址,让edi存放[ebp-0E4h]的位置,1C至2C表示对空间进行初始化,从edi所指向的位置开始向高地址进行拷贝,初始内容为0CCCCCCCCh,拷贝39次00B81422 mov ecx,39h00B81427 mov eax,0CCCCCCCCh 00B8142C rep stos dword ptr es:[edi] int a = 10;00B8142E mov dword ptr [a],0Ah //将10赋值于给a变量分配的空间int b = 20;00B81435 mov dword ptr [b],14h //将20赋值于给b变量分配的空间int ret=add(a, b);00B8143C mov eax,dword ptr [b] //进行传参,让寄存器eax存放b的值00B8143F push eax //将eax压栈00B81440 mov ecx,dword ptr [a] //进行传参,让寄存器ecx存放a的值00B81443 push ecx //将ecx压栈00B81444 call _add (0B810E6h) //call指令下一条地址,为add函数的调用及返回做准备——————————————————————————————————————00B810DC jmp 00B83BBE __ValidateImageBase:00B810E1 jmp 00B82910 _add:00B810E6 jmp 00B813C0 //即进入add函数_GetProcessHeap@0:00B810EB jmp 00B83C2A __RTC_SetErrorFuncW:——————————————————————————————————————int add(int a, int b) 4: {00B813C0 push ebp //ebp压栈,是main函数的ebp00B813C1 mov ebp,esp //让ebp指向esp的位置。00B813C3 sub esp,0CCh //esp指向[esp-0CCh]的位置,sub为减00B813C9 push ebx //分别将ebx、esi、edi压栈00B813CA push esi 00B813CB push edi 00DC13CC lea edi,[ebp-0CCh] //加载有效地址,让edi存放[ebp-0CCh]的位置,CC至DC表示对空间进行初始化,从edi所指向的位置开始向高地址进行拷贝,初始内容为0CCCCCCCCh,拷贝33次00DC13D2 mov ecx,33h 00DC13D7 mov eax,0CCCCCCCCh 00DC13DC rep stos dword ptr es:[edi] 5: int ret = 0;00DC13DE mov dword ptr [ebp-8],0 //将0放入[ebp-8]处 6: ret = a + b;00DC13E5 mov eax,dword ptr [ebp+8] //将[ebp+8]处的值10放入eax00DC13E8 add eax,dword ptr [ebp+0Ch] //将[ebp+0Ch]处的值20放入eax并相加,得eax中的值为30.00DC13EB mov dword ptr [ebp-8],eax //将eax的内容拷贝在[ebp-8]中,即ret变量 7: return ret;00DC13EE mov eax,dword ptr [ebp-8] //将ret的值存入eax中 8: }00DC13F1 pop edi //edi、esi、ebx、出栈,栈帧逐渐开始销毁00DC13F2 pop esi 00DC13F3 pop ebx 00DC13F4 mov esp,ebp //让esp指向ebp位置00DC13F6 pop ebp //弹出ebp,00DC13F7 ret //使其指向调用者调用函数之后的下一条指令的地址00B81444 call 00B810E6 //下一条指令地址出栈00B81449 add esp,8 //将之前放入栈的两个实参从栈中移除,esp下移00B8144C mov dword ptr [ebp-20h],eax //将eax中的值30放入[ebp-20h]中,函数调用也到此结束 14: return 0;
四、函数调用图
阅读全文
2 0
- 函数的调用过程,栈帧的创建和销毁
- 函数的调用过程,栈帧的创建和销毁。
- 函数的调用过程,栈帧的创建和销毁
- 函数的调用过程,栈帧的创建和销毁。
- 函数的调用过程,栈帧的创建和销毁
- 函数的调用过程,栈帧的创建和销毁
- 函数调用过程,栈帧的创建和销毁
- 函数调用过程,栈帧的创建和销毁
- 函数的调用过程,栈桢的创建和销毁
- 函数的调用过程,栈桢的创建和销毁。
- 函数的调用过程(栈帧的创建和销毁)
- 函数的调用(栈帧的创建和销毁)
- 函数的调用过程、栈帧的创建以及销毁
- 函数的调用过程,栈帧的创建与销毁
- 【C】函数的调用过程,栈帧的创建和销毁
- 谈谈函数的调用过程,栈帧的创建和销毁。
- 浅谈函数的调用过程,栈帧的创建和销毁,附图讲解
- 函数调用的具体过程以及栈帧的创建和销毁
- CountDownLatch--一组线程完成后其他线程才执行(一)
- Android自定义可标记日历
- Qt标准对话框之进度对话框(QProgressDialog)
- 习题
- 存储过程中的循环加判断
- 函数的调用过程(栈帧的创建和销毁)
- My-Blog搭建过程:如何让一个网站从零到可以上线访问
- JS 错误处理
- Codeforces Round #415 (Div. 2)-C. Do you want a date?
- leetcode之回溯backtracing专题1
- 计算MTF(SFR)的基本步骤,及sfrmat3和Mitre SFR 1.4进行比较
- 实战mycat读写分离和分库分表(1)-本地mysql多实例搭建
- win7上使用vs2010编译crtmpserver
- C++ 命名规范