子风.NET 进阶中......

路途多艱,唯勤是岸

 

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 

 

 

 

posted on 2012-11-27 11:20  子风  阅读(514)  评论(0编辑  收藏  举报

导航