简单反汇编代码如下:
#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从
//而返回到主函数中。
//由于不会添加图片,就只能把具体调用过程中栈空间分配的图作为附件添加了,不好意思!
- 标 题:C++反汇编函数调用代码详细分析
- 作 者:潜行修身
- 时 间:2010-04-06 14:11:34
- 链 接:http://bbs.pediy.com/showthread.php?t=110323