函数调用堆栈变化情况

来源:互联网 发布:电工考试软件 编辑:程序博客网 时间:2024/05/14 02:37
int goo(int a, int b)  
  1. {  
  2.     return a + b;  
  3. }  
  4.   
  5. void foo()  
  6. {  
  7.     int a[] = {1, 2, 3};  
  8.     int result = goo(a[1], a[2]);  
  9.     printf("result: %d", result);  
  10. }  

VS2010下编译


foo函数部分汇编:

[cpp] view plaincopyprint?
  1. 00EB3890  push        ebp    
  2. 00EB3891  mov         ebp,esp    
  3. 00EB3893  sub         esp,0E4h    
  4. 00EB3899  push        ebx    
  5. 00EB389A  push        esi    
  6. 00EB389B  push        edi    
  7. 00EB389C  lea         edi,[ebp-0E4h]    
  8. 00EB38A2  mov         ecx,39h    
  9. 00EB38A7  mov         eax,0CCCCCCCCh    
  10. 00EB38AC  rep stos    dword ptr es:[edi]    
  11. 00EB38AE  mov         eax,dword ptr [___security_cookie (0EB7000h)]    
  12. 00EB38B3  xor         eax,ebp    
  13. 00EB38B5  mov         dword ptr [ebp-4],eax    
  14.     int a[] = {1, 2, 3};  
  15. 00EB38B8  mov         dword ptr [ebp-14h],1    
  16. 00EB38BF  mov         dword ptr [ebp-10h],2    
  17. 00EB38C6  mov         dword ptr [ebp-0Ch],3    
  18.     int result = goo(a[1], a[2]);  
  19. 00EB38CD  mov         eax,dword ptr [ebp-0Ch]    
  20. 00EB38D0  push        eax    
  21. 00EB38D1  mov         ecx,dword ptr [ebp-10h]    
  22. 00EB38D4  push        ecx    
  23. 00EB38D5  call        goo (0EB11E5h)    
  24. 00EB38DA  add         esp,8    

goo函数完整汇编:

[cpp] view plaincopyprint?
  1. 00EB1580  push        ebp    
  2. 00EB1581  mov         ebp,esp    
  3. 00EB1583  sub         esp,0C0h    
  4. 00EB1589  push        ebx    
  5. 00EB158A  push        esi    
  6. 00EB158B  push        edi    
  7. 00EB158C  lea         edi,[ebp-0C0h]    
  8. 00EB1592  mov         ecx,30h    
  9. 00EB1597  mov         eax,0CCCCCCCCh    
  10. 00EB159C  rep stos    dword ptr es:[edi]    
  11.     return a + b;  
  12. 00EB159E  mov         eax,dword ptr [a]    
  13. 00EB15A1  add         eax,dword ptr [b]    
  14. }  
  15. 00EB15A4  pop         edi    
  16. 00EB15A5  pop         esi    
  17. 00EB15A6  pop         ebx    
  18. 00EB15A7  mov         esp,ebp    
  19. 00EB15A9  pop         ebp    
  20. 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等的可变参数个数功能,因为子函数不知道具体有多少要参数进入了,只有调用处才知道)

原创粉丝点击