当前位置:编程学习 > C/C++ >>

函数调用堆栈

这段代码反汇编后,代码是什么呢?

#include <stdio.h>

long test(int a,int b)
{
     a = a + 3;
     b = b + 5;
     return a + b;
}

int main(int argc, char* argv[])
{
    printf("%d",test(10,90));
    return 0;
}


先来看一个概貌

16:   int main(int argc, char* argv[])
17:   {
00401070   push        ebp
00401071   mov         ebp,esp
00401073   sub         esp,40h
00401076   push        ebx
00401077   push        esi
00401078   push        edi
00401079   lea         edi,[ebp-40h]
0040107C   mov         ecx,10h
00401081   mov         eax,0CCCCCCCCh
00401086   rep stos    dword ptr [edi]
18:       printf("%d",test(10,90));
00401088   push        5Ah
0040108A   push        0Ah
0040108C   call        @ILT+0(test) (00401005)
00401091   add         esp,8
00401094   push        eax
00401095   push        offset string "%d" (0042201c)
0040109A   call        printf (004010d0)
0040109F   add         esp,8
19:       return 0;
004010A2   xor         eax,eax
20:   }
 

下面来解释一下
\

开始进入Main函数  esp=0x12FF84   ebp=0x12FFC0
完成椭圆形框起来的部分
00401070   push        ebp     ebp的值入栈,保存现场(调用现场,从test函数看,如红线所示,即保存的0x12FF80用于从test函数堆栈返回到main函数)
00401071   mov         ebp,esp     此时ebp=0x12FF80 此时ebp就是“当前函数堆栈”的基址 以便访问堆栈中的信息;还有就是从当前函数栈顶返回到栈底

00401073   sub      esp,40h  
函数使用的堆栈,默认64个字节,堆栈上就是16个横条(密集线部分)此时esp=0x12FF40
在上图中,上面密集线是test函数堆栈空间,下面是Main的堆栈空间    (补充,其实这个就叫做 Stack Frame)

00401076   push        ebx
00401077   push        esi
00401078   push        edi    入栈

00401079   lea         edi,[ebp-40h]
0040107C   mov         ecx,10h
00401081   mov         eax,0CCCCCCCCh
00401086   rep stos    dword ptr [edi]     
初始化用于该函数的栈空间为0XCCCCCCCC  即从0x12FF40~0x12FF80所有的值均为0xCCCCCCCC

18:       printf("%d",test(10,90));
00401088   push        5Ah    参数入栈 从右至左 先90  后10
0040108A   push        0Ah

0040108C   call        @ILT+0(test) (00401005)  
函数调用,转向eip 00401005 
注意,此时仍入栈,入栈的是call test 指令下一条指令的地址00401091   下一条指令是add esp,8

@ILT+0(?test@@YAJHH@Z):
00401005   jmp         test (00401020)  
即转向被调函数test

8:    long test(int a,int b)
9:    {
00401020   push        ebp
00401021   mov         ebp,esp          
00401023   sub         esp,40h
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-40h]
0040102C   mov         ecx,10h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]       //这些和上面一样
10:        a = a + 3;                                   
00401038   mov         eax,dword ptr [ebp+8]     //ebp=0x12FF24 加8 [0x12FF30]即取到了参数10
0040103B   add         eax,3
0040103E   mov         dword ptr [ebp+8],eax
11:        b = b + 5;
00401041   mov         ecx,dword ptr [ebp+0Ch]
00401044   add         ecx,5
00401047   mov         dword ptr [ebp+0Ch],ecx
12:        return a + b;
0040104A   mov         eax,dword ptr [ebp+8]
0040104D   add         eax,dword ptr [ebp+0Ch]  //最后的结果保存在eax, 结果得以返回
13:   }
00401050   pop         edi                
00401051   pop         esi
00401052   pop         ebx
00401053   mov         esp,ebp     //esp指向0x12FF24, test函数的堆栈空间被放弃,从当前函数栈顶返回到栈底
00401055   pop         ebp           //此时ebp=0x12FF80, 恢复现场  esp=0x12FF28
00401056   ret                   &n

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,