c++ 函数的工作原理

目录

  • 函数传参
  • 结构体作为函数的返回值

1:函数传参

   

1  int Add( int a, int b)
2 {
3      return a+b;
4 }

     反汇编代码

30:        int i =  Add( 5, 6) ;
00401078    push         6  ; 参数入栈
0040107A    push         5  ; 参数入栈
0040107C    call        @ILT+ 5( Add) ( 0040100a)
00401081    add         esp, 8    ;由于push2个参数,esp-8,所以这里esp+8,平衡栈。
00401084    mov         dword ptr [ebp- 4],eax  ;eax为函数的返回值

此时内存中栈的内容

0012FF24  81 10 40 00  ..@.  ;Call的下一条指令的内存地址
0012FF28  05 00 00 00  ....  ;参数5
0012FF2C  06 00 00 00  ....  ;参数6
0012FF30  00 00 92 7C         

Add函数

00401030    push        ebp      ; 保存ebp
00401031    mov         ebp,esp  ; 赋值 ebp=esp ,ebp作为栈底
00401033    sub         esp,40h  ; 抬高栈,开辟40h个空间
00401036    push        ebx      ;ebx 入栈
00401037    push        esi      ;esi 入栈
00401038    push        edi      ; edi 入栈
00401039    lea         edi,[ebp-40h]  ;初始化栈40h为C
0040103C    mov         ecx,10h
00401041    mov         eax,0CCCCCCCCh
00401046    rep stos    dword ptr [edi]
8:        return a+b ;
00401048    mov         eax,dword ptr [ebp+ 8]  ;取出参数5
0040104B    add         eax,dword ptr [ebp+0Ch]; 取出参数6,返回值放在eax中
0040104E   pop         edi
0040104F   pop         esi
00401050   pop         ebx
00401051   mov         esp,ebp
00401053   pop         ebp
00401054   ret

栈的内存

00401030    push        ebp      ; 保存ebp
00401031    mov         ebp,esp  ; 赋值 ebp=esp ,ebp作为栈底,ebp = 12ff20
0012FF20   80 FF  12  00  .... ;12ff80是ebp的值,(ebp)
0012FF24   81  10  40  00  ..@. +4
0012FF28   05  00  00  00  .... +8
0012FF2C   06  00  00  00  .... +12
0012FF30   00  00  92 7C 
 
00401048    mov         eax,dword ptr [ebp+ 8]  ;取出参数5
0040104B    add         eax,dword ptr [ebp+0Ch]; 取出参数6;
[ebp+8] = 05
[ebp+C] = 06

2. 结构体作为函数的返回值

测试代码:

struct tagTest{
     int m_One ;
     int m_Two;
     int m_Three;
     int m_Four;
};

tagTest RerStruct()
{
    tagTest testRet;
    testRet.m_One =  1;
    testRet.m_Two =  2;
    testRet.m_Three =  3;
    testRet.m_Four =  4;
     return testRet;
}

反汇编代码:

30:       tagTest  test ;
31:        test = RerStruct() ;
00401078    lea         eax,[ebp-30h]  ;把ebp-30h的地址压入栈,函数的结构体赋值时候用
0040107B    push        eax
0040107C    call        @ILT+ 0(RerStruct) ( 00401005) ;执行完函数,此时ebp-30h上就完成了结构体返回值的拷贝
00401081    add         esp, 4  ;平衡堆栈
00401084    mov         ecx,dword ptr [eax]
00401086    mov         dword ptr [ebp-20h],ecx ;这里创建一个临时的结构体
00401089    mov         edx,dword ptr [eax+ 4] ; 位对位的copy
0040108C    mov         dword ptr [ebp-1Ch],edx
0040108F    mov         ecx,dword ptr [eax+ 8]
00401092    mov         dword ptr [ebp-18h],ecx
00401095    mov         edx,dword ptr [eax+0Ch]
00401098    mov         dword ptr [ebp-14h],edx
0040109B    mov         eax,dword ptr [ebp-20h]
0040109E    mov         dword ptr [ebp-10h],eax  ;赋值给test
004010A1    mov         ecx,dword ptr [ebp-1Ch]
004010A4    mov         dword ptr [ebp-0Ch],ecx
004010A7    mov         edx,dword ptr [ebp-18h]
004010AA    mov         dword ptr [ebp- 8],edx
004010AD    mov         eax,dword ptr [ebp-14h]
004010B0    mov         dword ptr [ebp- 4],eax

call        @ILT+0(RerStruct)

 

20:       tagTest testRet ;
21:       testRet.m_One =  1 ;
0040D7C8    mov         dword ptr [ebp-10h], 1
22:       testRet.m_Two =  2 ;
0040D7CF    mov         dword ptr [ebp-0Ch], 2
23:       testRet.m_Three =  3 ;
0040D7D6    mov         dword ptr [ebp- 8], 3
24:       testRet.m_Four =  4 ;
0040D7DD    mov         dword ptr [ebp- 4], 4
25:       return testRet ;
0040D7E4    mov         eax,dword ptr [ebp+ 8] ; 取出前面压入栈的eax
0040D7E7    mov         ecx,dword ptr [ebp-10h] ;位对位的copy
0040D7EA    mov         dword ptr [eax],ecx
0040D7EC    mov         edx,dword ptr [ebp-0Ch]
0040D7EF    mov         dword ptr [eax+ 4],edx
0040D7F2    mov         ecx,dword ptr [ebp- 8]
0040D7F5    mov         dword ptr [eax+ 8],ecx
0040D7F8    mov         edx,dword ptr [ebp- 4]
0040D7FB    mov         dword ptr [eax+0Ch],edx
0040D7FE    mov         eax,dword ptr [ebp+ 8]

这里有个疑问,为什么还要多创建一个临时的结构体?

此时栈中有3个结构体 ebp-30  ebp-20  ebp-10

 

0012FF50   01  00  00  00  ....
0012FF54   02  00  00  00  ....
0012FF58   03  00  00  00  ....
0012FF5C   04  00  00  00  ....
0012FF60   01  00  00  00  ....
0012FF64   02  00  00  00  ....
0012FF68   03  00  00  00  ....
0012FF6C   04  00  00  00  ....
0012FF70   01  00  00  00  ....
0012FF74   02  00  00  00  ....
0012FF78   03  00  00  00  ....
0012FF7C   04  00  00  00 

 

 

 

转载于:https://www.cnblogs.com/86188281/archive/2012/11/27/2790429.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值