C++反汇编代码分析--函数调用
代码如下:
#include "stdlib.h"
int sum(int a,int b,int m,int n)
{
return a+b;
}
void main()
{
int result = sum(1,2,3,4);
system("pause");
}
有四个参数的sum函数,接着在main方法中调用sum函数。在debug环境下,单步调试如下:
11: void main()
12: {
00401060 push ebp
;保存ebp,执行这句之前,ESP = 0012FF4C EBP = 0012FF88
;执行后,ESP = 0012FF48 EBP = 0012FF88,ESP减小,EBP不变
00401061 mov ebp,esp
;将esp放入ebp中,此时ebp和esp相同,即执行后ESP = 0012FF48 EBP = 0012FF48
;原EBP值已经被压栈(位于栈顶),而新的EBP又恰恰指向栈顶。
;此时EBP寄存器就已经处于一个非常重要的地位,该寄存器中存储着栈中的一个地址(原EBP入栈后的栈顶),
;从该地址为基准,向上(栈底方向)能获取返回地址、参数值(假如main中有参数,“获取参数值”会比较容易理解,
;不过在看下边的sum函数调用时会有体会的),向下(栈顶方向)能获取函数局部变量值,
;而该地址处又存储着上一层函数调用时的EBP值!
00401063 sub esp,44h
;把esp往上移动一个范围
;等于在栈中空出一片空间来存局部变量
;执行这句后ESP = 0012FF04 EBP = 0012FF48
00401066 push ebx
00401067 push esi
00401068 push edi
;保存三个寄存器的值
00401069 lea edi,[ebp-44h]
;把ebp-44h加载到edi中,目的是保存局部变量的区域
0040106C mov ecx,11h
00401071 mov eax,0CCCCCCCCh
00401076 rep stos dword ptr [edi]
;从ebp-44h开始的区域初始化成全部0CCCCCCCCh,就是int3断点,初始化局部变量空间
;REP ;CX不等于0 ,则重复执行字符串指令
;格式: STOS OPRD
;功能: 把AL(字节)或AX(字)中的数据存储到DI为目的串地址指针所寻址的存储器单元中去.指针DI将根据DF的值进行自动
;调整. 其中OPRD为目的串符号地址.
;以上的语句就是在栈中开辟一块空间放局部变量
;然后把这块空间都初始化为0CCCCCCCCh,就是int3断点,一个中断指令。
;因为局部变量不可能被执行,执行了就会出错,这时候发生中断提示开发者。
13: int result = sum(1,2,3,4);
00401078 push 4
0040107A push 3
0040107C push 2
0040107E push 1
;各个参数入栈,注意查看寄存器ESP值的变化
;亦可以看到参数入栈的顺序,从右到左
;变化为:ESP = 0012FEF8-->ESP = 0012FEF4-->ESP = 0012FEF0-->ESP = 0012FEEC-->ESP = 0012FEE8
00401080 call @ILT+15(boxer) (00401014)
;调用sum函数,可以按F11跟进
;注:f10(step over),单步调试,遇到函数调用,直接执行,不会进入函数内部
;f11(step into),单步调试,遇到函数调用,会进入函数内部
;shift+f11(step out),进入函数内部后,想从函数内部跳出,用此快捷方式
;ctrl+f10(run to cursor),呵呵,看英语注释就应该知道是什么意思了,不再解释
00401085 add esp,10h
;调用完函数