传值 ,传指针,传引用三种调用方式的反汇编

代码:
#include<iostream>
using namespace std;


int AddTwoNumber(int a,int b=8);//设置形参默认值
int  AddTwoNumber(int *,int *);
int AddTwoNum(int &,int &);

int main()
{
  int a=2,
    b=8;
  int result = AddTwoNumber(2,b);// 
  
  AddTwoNumber(&a,&b);

  AddTwoNum(a,b);

  return 0;
}

int  AddTwoNumber(int a,int b)
{
  return  a+b;
}

int  AddTwoNumber(int *pa,int *pb)
{
  return  *pa+*pb;
}

int  AddTwoNum(int &a,int &b)
{
  return  a+b;
}
  
  在Visual C++ 6.0中编译,链接后,用OD载入,按照第一课的方法找到Main函数入口,F7跟进,来到主函数体内
  
  00401050  /> \55            push    ebp          ; 保存ebp                     
  00401051  |.  8BEC          mov     ebp, esp     ;
  00401053  |.  83EC 4C       sub     esp, 4C      ;在堆栈中预留空间
  00401056  |.  53            push    ebx
  00401057  |.  56            push    esi
  00401058  |.  57            push    edi
  00401059  |.  8D7D B4       lea     edi, dword ptr [ebp-4C]
  0040105C  |.  B9 13000000   mov     ecx, 13
  00401061  |.  B8 CCCCCCCC   mov     eax, CCCCCCCC
  00401066  |.  F3:AB         rep     stos dword ptr es:[edi]
  00401068  |.  C745 FC 02000>mov     dword ptr [ebp-4], 2     ; 变量定义以及初始化
  0040106F  |.  C745 F8 08000>mov     dword ptr [ebp-8], 8     
  00401076  |.  8B45 F8       mov     eax, dword ptr [ebp-8]
  00401079  |.  50            push    eax
  0040107A  |.  6A 02         push    2
  0040107C  |.  E8 8EFFFFFF   call    0040100F               ;调用AddTwoNumber(int a,int b) ,传值调用
  00401081  |.  83C4 08       add     esp, 8
  00401084  |.  8945 F4       mov     dword ptr [ebp-C], eax
  00401087  |.  8D4D F8       lea     ecx, dword ptr [ebp-8]
  0040108A  |.  51            push    ecx
  0040108B  |.  8D55 FC       lea     edx, dword ptr [ebp-4]
  0040108E  |.  52            push    edx
  0040108F  |.  E8 76FFFFFF   call    0040100A               ;调用int  AddTwoNumber(int *pa,int *pb) 传址调用
  00401094  |.  83C4 08       add     esp, 8
  00401097  |.  8D45 F8       lea     eax, dword ptr [ebp-8]
  0040109A  |.  50            push    eax
  0040109B  |.  8D4D FC       lea     ecx, dword ptr [ebp-4]
  0040109E  |.  51            push    ecx
  0040109F  |.  E8 61FFFFFF   call    00401005               ;调用int  AddTwoNum(int &a,int &b)引用调用
  004010A4  |.  83C4 08       add     esp, 8
  004010A7  |.  33C0          xor     eax, eax
  004010A9  |.  5F            pop     edi
  004010AA  |.  5E            pop     esi
  004010AB  |.  5B            pop     ebx
  004010AC  |.  83C4 4C       add     esp, 4C
  004010AF  |.  3BEC          cmp     ebp, esp
  004010B1  |.  E8 AA710000   call    00408260
  004010B6  |.  8BE5          mov     esp, ebp
  004010B8  |.  5D            pop     ebp
  004010B9  \.  C3            retn






函数参数调用方式:

  
  一:
  传值调用: 函数调用时,实参的值传递给形参使用;
  
  1)程序中定义为:
  
  int  AddTwoNumber(int a,int b)
  {
    return  a+b;
  }
  
  2)反汇编后的代码为:
  参数入栈:
  00401079  |.  50            push    eax
  0040107A  |.  6A 02         push    2
  
  函数实现:
  
  004010E0  /> \55            push    ebp
  004010E1  |.  8BEC          mov     ebp, esp
  004010E3  |.  83EC 40       sub     esp, 40
  004010E6  |.  53            push    ebx
  004010E7  |.  56            push    esi
  004010E8  |.  57            push    edi
  004010E9  |.  8D7D C0       lea     edi, dword ptr [ebp-40]
  004010EC  |.  B9 10000000   mov     ecx, 10
  004010F1  |.  B8 CCCCCCCC   mov     eax, CCCCCCCC
  004010F6  |.  F3:AB         rep     stos dword ptr es:[edi]
  
  004010F8  |.  8B45 08       mov     eax, dword ptr [ebp+8]
  004010FB  |.  0345 0C       add     eax, dword ptr [ebp+C]
  004010FE  |.  5F            pop     edi
  004010FF  |.  5E            pop     esi
  00401100  |.  5B            pop     ebx
  00401101  |.  8BE5          mov     esp, ebp
  00401103  |.  5D            pop     ebp
  00401104  \.  C3            retn
  
  二:
  
  传址调用:形参为指针,实参为地址
  
  1)程序中定义为:
  
  int  AddTwoNumber(int *pa,int *pb)
  {
    return  *pa+*pb;
  }
  
  
  2)反汇编后的代码为:
  
  参数入栈:
  00401081  |.  83C4 08       add     esp, 8       ;调用者平衡被调用者的参数堆栈
  00401084  |.  8945 F4       mov     dword ptr [ebp-C], eax  ;int result = AddTwoNumber();
  
  00401087  |.  8D4D F8       lea     ecx, dword ptr [ebp-8]  ;注意这里,指针调用
  0040108A  |.  51            push    ecx
  0040108B  |.  8D55 FC       lea     edx, dword ptr [ebp-4]  
  0040108E  |.  52            push    edx
  
  函数实现:
  
  00401110  /> \55            push    ebp
  00401111  |.  8BEC          mov     ebp, esp
  00401113  |.  83EC 40       sub     esp, 40
  00401116  |.  53            push    ebx
  00401117  |.  56            push    esi
  00401118  |.  57            push    edi
  00401119  |.  8D7D C0       lea     edi, dword ptr [ebp-40]
  0040111C  |.  B9 10000000   mov     ecx, 10
  00401121  |.  B8 CCCCCCCC   mov     eax, CCCCCCCC
  00401126  |.  F3:AB         rep     stos dword ptr es:[edi]
  
  00401128  |.  8B45 08       mov     eax, dword ptr [ebp+8]
  0040112B  |.  8B00          mov     eax, dword ptr [eax]
  0040112D  |.  8B4D 0C       mov     ecx, dword ptr [ebp+C]
  00401130  |.  0301          add     eax, dword ptr [ecx]    ;在ecx寄存器上右键,数据窗口中跟随,地址是堆栈中的地址;
  00401132  |.  5F            pop     edi
  00401133  |.  5E            pop     esi
  00401134  |.  5B            pop     ebx
  00401135  |.  8BE5          mov     esp, ebp
  00401137  |.  5D            pop     ebp
  00401138  \.  C3            retn
  
  
  
  引用调用:形参为引用,实参为变量名 
  
  1)程序中定义为:
  
  int  AddTwoNum(int &a,int &b)
  {
    return  a+b;
  }
  
  2)反汇编后的代码为:
  参数入栈:
  00401097  |.  8D45 F8       lea     eax, dword ptr [ebp-8]
  0040109A  |.  50            push    eax
  0040109B  |.  8D4D FC       lea     ecx, dword ptr [ebp-4]
  0040109E  |.  51            push    ecx
  
  
  函数实现:
  00401150  /> \55            push    ebp
  00401151  |.  8BEC          mov     ebp, esp
  00401153  |.  83EC 40       sub     esp, 40
  00401156  |.  53            push    ebx
  00401157  |.  56            push    esi
  00401158  |.  57            push    edi
  00401159  |.  8D7D C0       lea     edi, dword ptr [ebp-40]
  0040115C  |.  B9 10000000   mov     ecx, 10
  00401161  |.  B8 CCCCCCCC   mov     eax, CCCCCCCC
  00401166  |.  F3:AB         rep     stos dword ptr es:[edi]
  00401168  |.  8B45 08       mov     eax, dword ptr [ebp+8]
  0040116B  |.  8B00          mov     eax, dword ptr [eax]
  0040116D  |.  8B4D 0C       mov     ecx, dword ptr [ebp+C]
  00401170  |.  0301          add     eax, dword ptr [ecx]
  00401172  |.  5F            pop     edi
  00401173  |.  5E            pop     esi
  00401174  |.  5B            pop     ebx
  00401175  |.  8BE5          mov     esp, ebp
  00401177  |.  5D            pop     ebp
  00401178  \.  C3            retn
  
  
  从上述我们可以看出,三种函数调用方式上 ,传值调用和后两种在参数的使用和功能实现上都有不同,由于是指针,
  所以在参数入栈时用了lea指令,并且,传址调用和引用调用的功能性代码完全相同,而且,用引用调用能简化书写,
  它们的不同,在这个程序中,唯一的区别就是参数入栈时,使用的寄存器不同;由于使用了Lea指令,传址调用和引用调用
  函数执行的时间肯定要比传值调用的时间长,所以如果是在函数的递归调用和嵌套调用中,如果为了效力考虑,在完成
  相同的功能的函数设计上,尽量使用传值调用;另外在传址调用和引用调用上,建议大家使用引用调用,因为它们在实现
  上一样的,而引用调用使用起来更加方便;
  并且有一点想让大家注意,大家在想栈这个数据结构,不要想着Push, pop后栈中的数据就不再了,
  物理内存一般为动态RAM,一般为MOS型,它具有客观实在性,因此,即使你pop平衡了栈后,原来的数据仍然存放在内存中
  也就是,除非断电或再一次被使用,否则内存中的数据不会改变
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值