首页
论坛
课程
招聘
[旧帖] [原创]C++反汇编函数调用代码详细分析 0.00雪花
2010-4-6 14:11 1508

[旧帖] [原创]C++反汇编函数调用代码详细分析 0.00雪花

2010-4-6 14:11
1508
简单反汇编代码如下:
#include <iostream>
using namespace std;
void swap(int &,int &);
int main()
{
     int a=19,b=24;
     swap(a,b);
     cout<<a<<endl<<b<<endl;
     return 0;
}

void swap(int & i,int & j)
{
     int temp;
     temp=i;
     i=j;
     j=temp;
}
/////////////////////////////////////////////////////////////////////////////////

//:反汇编代码详解:
//:反汇编环境为VC6.0

/////////////////////////////////////////////////////////////////////////////////
1: #include <iostream>
2: using namespace std;
3: void swap(int&,int&);
4: int main()
5: {
         00401560 push ebp
//在程序运行开始先将原ebp值压栈,执行前ebp=0012FF88,esp=0012FF4C。
      00401561 mov ebp,esp
         00401563 sub esp,48h
//由于程序执行调用main函数,main函数就会产生一栈帧空间。esp始终指向栈顶的下一位置,因此将esp给ebp,将esp指针下移48h空间,所分配的
//48h空间就可以被利用,执行完后ebp=0012FF48,esp=0012FF00。
      00401566 push ebx
         00401567 push esi
         00401568 push edi
//保存原寄存器的值,当然由于esp指向80012FF00,因此ebx,esi,edi三个寄存器被压入栈的地址应为0012FF0C、0012FEF8、0012FEF4。
      00401569 lea edi,[ebp-48h]
         0040156C mov ecx,12h
         00401571 mov eax,0CCCCCCCCh
         00401576 rep stos dword ptr [edi]
//将所分配的48h空间写满0CCCCCCCCh,即int 3的十六位机器码。用于初始化局部变量空间
6: int a=19,b=24;
         00401578 mov dword ptr [ebp-4],13h
         0040157F mov dword ptr [ebp-8],18h
//将a、b的值写入局部变量空间的前两个双字空间,13h放入0012FF44中,18h放入0012FF40
7: swap(a,b);
         00401586 lea eax,[ebp-8]
         00401589 push eax
         0040158A lea ecx,[ebp-4]
         0040158D push ecx
         0040158E call @ILT+465(swap) (004011d6)
         00401593 add esp,8
//调用swap函数前先将[ebp-8]、[ebp-4]地址压栈,即a和b的地址。在栈中所占用的地址就是
//0012FEF0和0012FEEC。这里可以很清楚的看到00401593是被调函数返回以后执行的第一
//条指令,该指令的作用是清空堆栈。call指令在此隐含的做了一个压栈操作:将函数返回后执行的
//第一条指令压入堆栈。由内存空间可以看出:
//0012FEE8 93 15 40 00 44 FF 12 00 40 FF 12 00 00 00 00 00 00 00 00 00 00
//将地址00401593已经压入栈中。
8: cout<<a<<endl<<b<<endl;
         00401596 push offset @ILT+195(std::endl) (004010c8)
         0040159B mov edx,dword ptr [ebp-8]
         0040159E push edx
         0040159F push offset @ILT+195(std::endl) (004010c8)
         004015A4 mov eax,dword ptr [ebp-4]
         004015A7 push eax
         004015A8 mov ecx,offset std::cout (0047be90)
         004015AD call @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff)
         004015B2 mov ecx,eax
         004015B4 call @ILT+480(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e5)
         004015B9 mov ecx,eax
         004015BB call @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff)
         004015C0 mov ecx,eax
         004015C2 call @ILT+480(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e5)
//调用库函数
9: return 0;
         004015C7 xor eax,eax
//将eax置0,用于函数的返回值。一般若函数有返回值,将返回值放入eax中返回。
10: }
         004015C9 pop edi
         004015CA pop esi
         004015CB pop ebx
         004015CC add esp,48h
         004015CF cmp ebp,esp
         004015D1 call __chkesp (004205b0)
         004015D6 mov esp,ebp
         004015D8 pop ebp
         004015D9 ret
//弹出寄存器edi,esi,ebx。恢复esp,检查esp是否正常,若不正常进入debug
//恢复原来的esp和ebp的值用于上层的函数使用。ret指令将栈顶返回地址送给eip

//接下来进入call @ILT+465(swap) (004011d6),调用swap的过程:
12:   void swap(int& i,int& j)
13:   {
         00401600   push        ebp
         00401601   mov         ebp,esp
         00401603   sub         esp,44h
         00401606   push        ebx
         00401607   push        esi
         00401608   push        edi
         00401609   lea         edi,[ebp-44h]
         0040160C   mov         ecx,11h
         00401611   mov         eax,0CCCCCCCCh
         00401616   rep stos    dword ptr [edi]
//此处与main函数开头唯一不同的是此处分配了44h的局部变量空间,其他的都相同
14:
15:
16:       int temp;
17:
18:
19:       temp=i;
         00401618   mov         eax,dword ptr [ebp+8]
         0040161B   mov         ecx,dword ptr [eax]
         0040161D   mov         dword ptr [ebp-4],ecx
//指定局部变量空间的第一个双字节地址处为temp空间,在此直接读取的是上个栈帧中的内容
20:       i=j;
         00401620   mov         edx,dword ptr [ebp+8]
         00401623   mov         eax,dword ptr [ebp+0Ch]
         00401626   mov         ecx,dword ptr [eax]
         00401628   mov         dword ptr [edx],ecx
21:       j=temp;
         0040162A   mov         edx,dword ptr [ebp+0Ch]
         0040162D   mov         eax,dword ptr [ebp-4]
         00401630   mov         dword ptr [edx],eax
//交换操作实际是[ebp+8]、[ebp+oCh]、[ebp-4]直接的交换。
22:   }
         00401632   pop         edi
         00401633   pop         esi
         00401634   pop         ebx
         00401635   mov         esp,ebp
         00401637   pop         ebp
         00401638   ret
//弹出edi、esi、ebx的值。恢复上一层ebp和esp中的内容。同样ret指令将栈顶内容送给eip从
//而返回到主函数中。

//由于不会添加图片,就只能把具体调用过程中栈空间分配的图作为附件添加了,不好意思!

[2022冬季班]《安卓高级研修班(网课)》月薪三万班招生中~

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回