【转】函数调用时堆栈变化
- int goo(int a, int b)
- {
- return a + b;
- }
- void foo()
- {
- int a[] = {1, 2, 3};
- int result = goo(a[1], a[2]);
- printf("result: %d", result);
- }
VS2010下编译
foo函数部分汇编:
- 00EB3890 push ebp
- 00EB3891 mov ebp,esp
- 00EB3893 sub esp,0E4h
- 00EB3899 push ebx
- 00EB389A push esi
- 00EB389B push edi
- 00EB389C lea edi,[ebp-0E4h]
- 00EB38A2 mov ecx,39h
- 00EB38A7 mov eax,0CCCCCCCCh
- 00EB38AC rep stos dword ptr es:[edi]
- 00EB38AE mov eax,dword ptr [___security_cookie (0EB7000h)]
- 00EB38B3 xor eax,ebp
- 00EB38B5 mov dword ptr [ebp-4],eax
- int a[] = {1, 2, 3};
- 00EB38B8 mov dword ptr [ebp-14h],1
- 00EB38BF mov dword ptr [ebp-10h],2
- 00EB38C6 mov dword ptr [ebp-0Ch],3
- int result = goo(a[1], a[2]);
- 00EB38CD mov eax,dword ptr [ebp-0Ch]
- 00EB38D0 push eax
- 00EB38D1 mov ecx,dword ptr [ebp-10h]
- 00EB38D4 push ecx
- 00EB38D5 call goo (0EB11E5h)
- 00EB38DA add esp,8
- 00EB3890 push ebp
- 00EB3891 mov ebp,esp
- 00EB3893 sub esp,0E4h
- 00EB3899 push ebx
- 00EB389A push esi
- 00EB389B push edi
- 00EB389C lea edi,[ebp-0E4h]
- 00EB38A2 mov ecx,39h
- 00EB38A7 mov eax,0CCCCCCCCh
- 00EB38AC rep stos dword ptr es:[edi]
- 00EB38AE mov eax,dword ptr [___security_cookie (0EB7000h)]
- 00EB38B3 xor eax,ebp
- 00EB38B5 mov dword ptr [ebp-4],eax
- int a[] = {1, 2, 3};
- 00EB38B8 mov dword ptr [ebp-14h],1
- 00EB38BF mov dword ptr [ebp-10h],2
- 00EB38C6 mov dword ptr [ebp-0Ch],3
- int result = goo(a[1], a[2]);
- 00EB38CD mov eax,dword ptr [ebp-0Ch]
- 00EB38D0 push eax
- 00EB38D1 mov ecx,dword ptr [ebp-10h]
- 00EB38D4 push ecx
- 00EB38D5 call goo (0EB11E5h)
- 00EB38DA add esp,8
goo函数完整汇编:
- 00EB1580 push ebp
- 00EB1581 mov ebp,esp
- 00EB1583 sub esp,0C0h
- 00EB1589 push ebx
- 00EB158A push esi
- 00EB158B push edi
- 00EB158C lea edi,[ebp-0C0h]
- 00EB1592 mov ecx,30h
- 00EB1597 mov eax,0CCCCCCCCh
- 00EB159C rep stos dword ptr es:[edi]
- return a + b;
- 00EB159E mov eax,dword ptr [a]
- 00EB15A1 add eax,dword ptr [b]
- }
- 00EB15A4 pop edi
- 00EB15A5 pop esi
- 00EB15A6 pop ebx
- 00EB15A7 mov esp,ebp
- 00EB15A9 pop ebp
- 00EB15AA ret
- 00EB1580 push ebp
- 00EB1581 mov ebp,esp
- 00EB1583 sub esp,0C0h
- 00EB1589 push ebx
- 00EB158A push esi
- 00EB158B push edi
- 00EB158C lea edi,[ebp-0C0h]
- 00EB1592 mov ecx,30h
- 00EB1597 mov eax,0CCCCCCCCh
- 00EB159C rep stos dword ptr es:[edi]
- return a + b;
- 00EB159E mov eax,dword ptr [a]
- 00EB15A1 add eax,dword ptr [b]
- }
- 00EB15A4 pop edi
- 00EB15A5 pop esi
- 00EB15A6 pop ebx
- 00EB15A7 mov esp,ebp
- 00EB15A9 pop ebp
- 00EB15AA ret
foo函数push ebp, mov ebp, esp后
保存原ebp,设定新的ebp为当前esp位置
sub esp, 0E4h
给局部变量分配足够大的栈空间
保存原先的一些寄存器值,每次push,esp继续向下移
为局部变量a数组赋值
调用goo前Push两个参数,esp继续下移
call goo函数时,cpu自动push下一条指令地址,esp继续下移
在goo函数中,同样保存foo函数中的ebp值,设定新的ebp,esp等
在执行玩goo函数最后几句指令时,edi, esi, ebx恢复,esp同时也编程goo中ebp的位置,ebp恢复至foo函数原来的位置(pop ebp)
下一条指令也装入IP(ret指令),esp继续向上一步
foo函数中的add esp, 8将esp值继续往上(清除函数参数)
清除函数参数的工作也可通过ret X在goo函数返回时设定(这样的话不必在每次调用点上加上add esp, X指令缩短了编译出来的文件大小,但在子函数中清除将不能做到printf等的可变参数个数功能,因为子函数不知道具体有多少要参数进入了,只有调用处才知道)
转载于:https://www.cnblogs.com/zzmx/p/4166443.html
【转】函数调用时堆栈变化相关推荐
- C++函数调用时堆栈的变化情况
代码编译运行环境:VS2017+Debug+Win32 1.栈帧简介 函数的运行是在栈上展开的,每一个函数在被调用时所占用的内存空间就是栈,栈保存了一个函数调用需要维护的信息.函数栈通常被称为栈帧(S ...
- 从函数调用过程中的堆栈变化理解缓冲区溢出
一.说明 本来是想直接写一个缓冲区溢出的例子,但是一是当前编译器和操作系统有溢出的保护措施没有完全弄清怎么取消,二是strcpy等遇到00会截断需要进行编码这比较难搞,所以最终没有实现. 但已经双看了 ...
- 献给汇编初学者-函数调用堆栈变化分析
献给汇编初学者-函数调用堆栈变化分析 标 题: 献给汇编初学者-函数调用堆栈变化分析 作 者: 堕落天才 时 间: 2007-01-19,19:20 链 接: http://bbs.pediy.com ...
- 对PInvoke函数函数调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。...
C#引入外部非托管类库时,有时候会出现"对PInvoke函数调用导致堆栈不对称.原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配"的报错. 通常在DllImport标 ...
- ARM函数调用时参数传递规则
之前在学习如何在C语言中嵌入汇编时有了解到C语言之前的参数调用是使用寄存器 R0传递第一个参数, R1传递到第二个.. 一直到R3传递第四个参数. 但是 实际上有时可能传递的参数非常多,超过8个,或是 ...
- 在c语言程序中,数组名做函数调用的实参时,传递给形参的是,若用数组名作为函数调用时的实参,则实际上传递给的形参的是(C)...
若用数组名作为函数调用时的实参,则实际上传递给形参的是数组首地址. 数组首地址数组第一个元素的地址.数组名字本身就是一个指针,它是一个指针常量,指向的地址不变. 比如定义了一个数组变量,编译器就会在内 ...
- C/C++函数调用时参数传递过程、调用约定与可变参函数的实现
目录 1.参数传递过程 2.参数压栈顺序从右至左的影响 3.调用约定 3.1.__cdecl C/C++ 缺省调用约定 3.2. __stdcall调用约定 3.3. __fastcall (快速调用 ...
- C#调用C/C++动态库dll异常:对 PInvoke 函数调用导致堆栈不对称问题
结论:如果你是用C#调用C的动态库,如果出现"对 PInvoke 函数调用导致堆栈不对称问题",建议优先调整CallingConvention的值,建议改为CallingConve ...
- 【总结整理】javascript的函数调用时是否加括号
javascript的函数调用时是否加括号 if(event.preventDefault){ event.preventDefault(); if判断条件里面不要加括号,不加括号是应该以属性形式,i ...
最新文章
- 钻进眼球的致盲寄生虫威胁近亿人,却只是生存竞争的失败者
- Cvmat IplImage
- redis存opc_KEPServerEX6完整免费版
- (译)你应该知道的jQuery技巧
- 利用维纳滤波编码实现给定的运动模糊图像恢复
- maven 总结整理(二)——download source code
- 用Spire.doc来合并邮件
- 大数据集群跨多版本升级、业务0中断,只因背后有TA
- 右侧按钮登录注册html,翻转式用户登录注册界面设计
- java安装时无法写入文件_Java - 无法写入第二个文件
- [总结] 本人代表性博客总结
- oracle安装失败 主机名_PeopleTool 8.58.04 安装
- 用grub4dos制作U盘启动盘winpe+红叶dos+maxdos+veket+linuxmint
- Unity粒子系统-粒子光环
- Android 9.0 10.0 手动安装Persistent app失败的解决方案
- ExpandableListView中不同条目的位置不同的显示位置
- 如何使用Hyper-V Manager和Powershell合并Hyper-V检查点
- 讯飞 AIUI 集成
- [Java]Spring Ioc讲解,不怕你不懂
- npm run dev命令报错解决方式
热门文章
- java 二维数组位置_请完成下列Java程序:查找一个矩阵中的鞍点,对于一个二维数组中的鞍点,该点位置上的元素在该行上...
- 【若依(ruoyi)】打开新的选项卡
- 【maven】dependency的systemPath属性:引入本地系统中的jar
- 最长回文串--动态规划
- python翻页_python实现电子书翻页小程序
- 技嘉主板万能网卡驱动_技嘉Z490系列主板来袭:16相供电/钽电容,堆料更进一步...
- php+字符串去掉反斜杠,PHP如何去掉反斜杠?
- linux定时器回调处理过程,Linux内核系统定时器TIMER实现过程分析
- java 命令行eclipse_在命令行中运行eclipse中创建的java项目
- 四阶显式Adams法求方程组C语言,第五讲第4章线性多步法(续