戻り値がstructまたはclassオブジェクトである場合【4】

12777 ワード

C++コード:
struct AB
{
	int ia;
	int ib;
	int ic;
	AB(){}

};
AB su_4()    //       
{
	AB c;
	c.ia=100;
	c.ib=150;
	c.ic=200;
	
	return c;
}


int main()
{
	AB r;
	r=su_4();  //     

	getchar();
	return 0;
}

F 7コンパイル接続(debugモード).ブレークポイントを追加し、F 5でデバッグし、alt+8で逆アセンブリウィンドウが表示されます.アセンブリコードは次のとおりです.
    51: int main()
    52: {
004115F0 55                   push        ebp  				% 【1】    main            
004115F1 8B EC                mov         ebp,esp  
004115F3 81 EC E8 00 00 00    sub         esp,0E8h  
004115F9 53                   push        ebx  
004115FA 56                   push        esi  
004115FB 57                   push        edi  
004115FC 8D BD 18 FF FF FF    lea         edi,[ebp-0E8h]  
00411602 B9 3A 00 00 00       mov         ecx,3Ah  
00411607 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
0041160C F3 AB                rep stos    dword ptr es:[edi]  		% end 【1】
    60: 	AB r;
0041160E 8D 4D F0             lea         ecx,[r]  			% 【2】    ,      
00411611 E8 30 FA FF FF       call        AB::AB (411046h)  
    61: 	r=su_4();
00411616 8D 85 1C FF FF FF    lea         eax,[ebp-0E4h]   % 【3】  su_4()  。         ,         (    64bit),                                                                   %    。       ebp-0E4h,      ,        。        eax, push 
0041161C 50                   push        eax  
0041161D E8 65 FA FF FF       call        su_4 (411087h)   %     。eip    。
00411622 83 C4 04             add         esp,4  	   %     push eax,   esp   ,     。
00411625 8B 08                mov         ecx,dword ptr [eax]  		% eax                。  12  ,     mov    。                                                                            %              r  。
00411627 89 4D F0             mov         dword ptr [r],ecx  
0041162A 8B 50 04             mov         edx,dword ptr [eax+4]  
0041162D 89 55 F4             mov         dword ptr [ebp-0Ch],edx  
00411630 8B 40 08             mov         eax,dword ptr [eax+8]  
00411633 89 45 F8             mov         dword ptr [ebp-8],eax  

 
   105: 	getchar();					% 【4】    main      ,   。
00411636 8B F4                mov         esi,esp  
00411638 FF 15 B4 82 41 00    call        dword ptr [__imp__getchar (4182B4h)]  
0041163E 3B F4                cmp         esi,esp  
00411640 E8 FB FA FF FF       call        @ILT+315(__RTC_CheckEsp) (411140h)  
   106: 	return 0;
00411645 33 C0                xor         eax,eax  
   107: }
00411647 52                   push        edx  
00411648 8B CD                mov         ecx,ebp  
0041164A 50                   push        eax  
0041164B 8D 15 6C 16 41 00    lea         edx,[ (41166Ch)]  
00411651 E8 2C FA FF FF       call        @ILT+125(@_RTC_CheckStackVars@8) (411082h)  
00411656 58                   pop         eax  
00411657 5A                   pop         edx  
00411658 5F                   pop         edi  
00411659 5E                   pop         esi  
0041165A 5B                   pop         ebx  
0041165B 81 C4 E8 00 00 00    add         esp,0E8h  
00411661 3B EC                cmp         ebp,esp  
00411663 E8 D8 FA FF FF       call        @ILT+315(__RTC_CheckEsp) (411140h)  
00411668 8B E5                mov         esp,ebp  
0041166A 5D                   pop         ebp  
0041166B C3                   ret  


    :
   26: struct AB
    27: {
    28: 	int ia;
    29: 	int ib;
    30: 	int ic;
    31: 	AB(){}
004115B0 55                   push        ebp  
004115B1 8B EC                mov         ebp,esp  
004115B3 81 EC CC 00 00 00    sub         esp,0CCh  
004115B9 53                   push        ebx  
004115BA 56                   push        esi  
004115BB 57                   push        edi  
004115BC 51                   push        ecx  
004115BD 8D BD 34 FF FF FF    lea         edi,[ebp-0CCh]  
004115C3 B9 33 00 00 00       mov         ecx,33h  
004115C8 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
004115CD F3 AB                rep stos    dword ptr es:[edi]  
004115CF 59                   pop         ecx  
004115D0 89 4D F8             mov         dword ptr [ebp-8],ecx  
004115D3 8B 45 F8             mov         eax,dword ptr [this]  
004115D6 5F                   pop         edi  
004115D7 5E                   pop         esi  
004115D8 5B                   pop         ebx  
004115D9 8B E5                mov         esp,ebp  
004115DB 5D                   pop         ebp  
004115DC C3                   ret  
};



  :
   35: AB su_4()
    36: {
004114F0 55                   push        ebp  		%【1】        。
004114F1 8B EC                mov         ebp,esp  
004114F3 81 EC D4 00 00 00    sub         esp,0D4h  
004114F9 53                   push        ebx  
004114FA 56                   push        esi  
004114FB 57                   push        edi  
004114FC 8D BD 2C FF FF FF    lea         edi,[ebp-0D4h]  
00411502 B9 35 00 00 00       mov         ecx,35h  
00411507 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
0041150C F3 AB                rep stos    dword ptr es:[edi]  
    37: 	AB c;
0041150E 8D 4D F0             lea         ecx,[c]  	%【2】       ,      。
00411511 E8 30 FB FF FF       call        AB::AB (411046h)  
    38: 	c.ia=100;
00411516 C7 45 F0 64 00 00 00 mov         dword ptr [c],64h  	% 【3】          。
    39: 	c.ib=150;
0041151D C7 45 F4 96 00 00 00 mov         dword ptr [ebp-0Ch],96h  
    40: 	c.ic=200;
00411524 C7 45 F8 C8 00 00 00 mov         dword ptr [ebp-8],0C8h  
    41: 	
    42: 	return c;
0041152B 8B 45 08             mov         eax,dword ptr [ebp+8]   %【4】     。 ebp         ebp,ebp+4     eip,eip+8                                                                           %    。         eax。
0041152E 8B 4D F0             mov         ecx,dword ptr [c]       % [c]   [ebp-4]。     c             。
00411531 89 08                mov         dword ptr [eax],ecx  
00411533 8B 55 F4             mov         edx,dword ptr [ebp-0Ch]  
00411536 89 50 04             mov         dword ptr [eax+4],edx  
00411539 8B 4D F8             mov         ecx,dword ptr [ebp-8]  
0041153C 89 48 08             mov         dword ptr [eax+8],ecx  
0041153F 8B 45 08             mov         eax,dword ptr [ebp+8]  
    43: }
00411542 52                   push        edx  			 % 【5】      。
00411543 8B CD                mov         ecx,ebp  
00411545 50                   push        eax  
00411546 8D 15 68 15 41 00    lea         edx,[ (411568h)]  
0041154C E8 31 FB FF FF       call        @ILT+125(@_RTC_CheckStackVars@8) (411082h)  
00411551 58                   pop         eax  
00411552 5A                   pop         edx  
00411553 5F                   pop         edi  
00411554 5E                   pop         esi  
00411555 5B                   pop         ebx  
00411556 81 C4 D4 00 00 00    add         esp,0D4h  
0041155C 3B EC                cmp         ebp,esp  
0041155E E8 DD FB FF FF       call        @ILT+315(__RTC_CheckEsp) (411140h)  
00411563 8B E5                mov         esp,ebp  
00411565 5D                   pop         ebp  
00411566 C3                   ret 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
以上が構造関数がある場合,structはクラスとして解釈される.コンストラクション関数がない場合は、コピーが1回増えます.
   51: int main()
    52: {
004115A0 55                   push        ebp  
004115A1 8B EC                mov         ebp,esp  
004115A3 81 EC 00 01 00 00    sub         esp,100h  
004115A9 53                   push        ebx  
004115AA 56                   push        esi  
004115AB 57                   push        edi  
004115AC 8D BD 00 FF FF FF    lea         edi,[ebp-100h]  
004115B2 B9 40 00 00 00       mov         ecx,40h  
004115B7 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
004115BC F3 AB                rep stos    dword ptr es:[edi]  
004115BE A1 00 70 41 00       mov         eax,dword ptr [___security_cookie (417000h)]  
004115C3 33 C5                xor         eax,ebp  
004115C5 89 45 FC             mov         dword ptr [ebp-4],eax  

    60: 	AB r;
    61: 	r=su_4();
004115C8 8D 85 18 FF FF FF    lea         eax,[ebp-0E8h]  
004115CE 50                   push        eax  
004115CF E8 AE FA FF FF       call        su_4 (411082h)  
004115D4 83 C4 04             add         esp,4  
004115D7 8B 08                mov         ecx,dword ptr [eax]  			%     
004115D9 89 8D 04 FF FF FF    mov         dword ptr [ebp-0FCh],ecx  
004115DF 8B 50 04             mov         edx,dword ptr [eax+4]  
004115E2 89 95 08 FF FF FF    mov         dword ptr [ebp-0F8h],edx  
004115E8 8B 40 08             mov         eax,dword ptr [eax+8]  
004115EB 89 85 0C FF FF FF    mov         dword ptr [ebp-0F4h],eax  
004115F1 8B 8D 04 FF FF FF    mov         ecx,dword ptr [ebp-0FCh]  
004115F7 89 4D EC             mov         dword ptr [ebp-14h],ecx  
004115FA 8B 95 08 FF FF FF    mov         edx,dword ptr [ebp-0F8h]  
00411600 89 55 F0             mov         dword ptr [ebp-10h],edx  
00411603 8B 85 0C FF FF FF    mov         eax,dword ptr [ebp-0F4h]  
00411609 89 45 F4             mov         dword ptr [ebp-0Ch],eax  
    62: 
   104: 
   105: 	getchar();
0041160C 8B F4                mov         esi,esp  
0041160E FF 15 B4 82 41 00    call        dword ptr [__imp__getchar (4182B4h)]  
00411614 3B F4                cmp         esi,esp  
00411616 E8 20 FB FF FF       call        @ILT+310(__RTC_CheckEsp) (41113Bh)  
   106: 	return 0;
0041161B 33 C0                xor         eax,eax  
   107: }
0041161D 52                   push        edx  
0041161E 8B CD                mov         ecx,ebp  
00411620 50                   push        eax  
00411621 8D 15 4C 16 41 00    lea         edx,[ (41164Ch)]  
00411627 E8 51 FA FF FF       call        @ILT+120(@_RTC_CheckStackVars@8) (41107Dh)  
0041162C 58                   pop         eax  
0041162D 5A                   pop         edx  
0041162E 5F                   pop         edi  
0041162F 5E                   pop         esi  
00411630 5B                   pop         ebx  
00411631 8B 4D FC             mov         ecx,dword ptr [ebp-4]  
00411634 33 CD                xor         ecx,ebp  
00411636 E8 D9 F9 FF FF       call        @ILT+15(@__security_check_cookie@4) (411014h)  
0041163B 81 C4 00 01 00 00    add         esp,100h  
00411641 3B EC                cmp         ebp,esp  
00411643 E8 F3 FA FF FF       call        @ILT+310(__RTC_CheckEsp) (41113Bh)  
00411648 8B E5                mov         esp,ebp  
0041164A 5D                   pop         ebp  
0041164B C3                   ret  

基本的に3回のコピーがあります.サブ関数では、変数を一時的に戻り値ストレージにコピーし、呼び出し側で別の一時ストレージにコピーし、そのストレージから受け入れられた変数にコピーします.
関数呼び出しの手順を明確にします.
(1)パラメータを右から左に入力してスタックに入り、参照するとpush変数のアドレスになる.
(2)戻り値が大きいオブジェクト(64 bitより大きい)であり、直接戻りであり、戻り参照ではない場合(戻り参照であれば直接アドレスを返す)は、遠いメモリを探して、そのアドレスpushをスタックに入れ、将来的には到来時に戻り値を格納する
(3)call funcを指す.funcは関数名です.このときeipレジスタのコンテンツは自動的にスタックされます.
(4)ここから関数に入ります!Push ebp、callerのebpをスタックに入れます.
(5)mov ebp, esp.現在のスタックトップはスタックベースとして使用されます.calleeは自分のスタックスペースを持っています!
(6)sub esp,100.100は勝手に書いてあるので、別の数かもしれません.システムは一時変数の空間を割り当てます.
(7)ebx,esi,ediなどのレジスタがスタックに入る.
(8)上記申請のスペースを0 xCCで埋める.
(9)仕事をする...
(10)関数が返されます.戻り値は大きなオブジェクトです.オブジェクトをebp+8の場所の値が指す位置にコピーします.そうですね.(2)ステップ目で戻り値を一時的に格納する場所を指します.
(11)mov esp,ebp.スタックスペースをクリーンアップするのは簡単ですが、スタックの上部の位置を変更すればいいです.
(12)ret.このコマンドはスタック内のeipに対応する値をポップアップし、この関数を呼び出した後の次のコマンドが何であるかを知ることができます.
(13)add esp,XXX.入力パラメータと一時保存スペースポインタがあるので、ここでスタックバランスを作ります.
(14)先ほど述べた戻り値一時格納空間から戻り値を別の一時格納空間にコピーする.この戻り値を受け入れる変数がある場合は、新しい一時保存スペースからその変数にコピーします.変数が受け入れられない場合は、使用しません.
(15)呼び出しが終了し,何をすべきか.
注:スタックスペースは一般的にデフォルト1 Mで、再帰的に深すぎるとスタックがオーバーフローします.
ref:
http://wenku.baidu.com/view/bea115ccda38376baf1faec7.html
http://www.cnblogs.com/zplutor/archive/2011/09/25/2190315.html