this指針與__thiscall調用方式

__thiscall 是爲了解決類成員調用中this指針傳遞而規定的。__thiscall要求把this指針放在特定寄存器中,該寄存器由編譯器決定。VC使用ecx,Borland的C++編譯器使用eax。

注 : 測試環境爲VS2012 , 編譯方式爲Debug版.

測試代碼:

#include "stdafx.h"

struct MyStruct
{
	int x ;
	int y ;
	void Plus(int a, int b )
	{
		printf("%d\n",x+y+a+b) ;
	}
    
};

void Plus(int a,int b)
{
	printf("%d\n",1+2+a+b) ;
}
int _tmain(int argc, _TCHAR* argv[])
{
	MyStruct haha ;
	haha.x = 1 ;
	haha.y = 2 ;
	haha.Plus(3,4);
	Plus(3,4);
	return 0;
}

以上測試代中結構體內碼成員函數是__thiscall調用方式 , 結構體外定義的Plus()函數 VS2012是默認__cdecl(即C調用方式) , 下面主要從三個方面比較兩種調用方式區別

A : 參數傳遞順序

B : 參數傳遞方式

C : 堆棧平衡

下面是兩個函數內部的反彙編代碼 :


    26:     haha.Plus(3,4);
013C3BA6 6A 04                push        4                          <span style="color:#009900;">/* 參數1 入棧 */</span>
013C3BA8 6A 03                push        3                          <span style="color:#009900;">/* 參數2 入棧 */</span>
013C3BAA 8D 4D F0             lea         ecx,[ebp-10h]              <span style="color:#009900;">/* this指針用ecx傳遞 */</span>
013C3BAD E8 56 D6 FF FF       call        013C1208  
    27:     Plus(3,4);
013C3BB2 6A 04                push        4  
013C3BB4 6A 03                push        3  
013C3BB6 E8 52 D6 FF FF       call        013C120D  
013C3BBB 83 C4 08             add         esp,8                      <span style="color:#009900;">/* 調用者平衡堆棧 */</span>

 



                                                                            A : 參數傳遞順序                                                B : 參數傳遞方式                                                   C : 堆棧平衡

__thiscall( 即 <span style="color:#3333FF;">haha.Plus(3,4)</span> ) : 自右向左傳參,最後傳遞this指針        普通參數用棧傳遞,this指針用ecx傳遞          被調用者平衡堆棧(內平棧)

__cdecl( 即 haha.Plus(3,4) )             :  自右向左傳參                                                    棧傳遞                                                                            調用者平衡堆棧(外平棧)

 


/************************************************************

*

* haha.Plus(3,4)函數內部(即__thiscall調用方式)

*

************************************************************/

    10: 	void Plus(int a, int b )
    11: 	{
013C39C0 55                   push        ebp  
013C39C1 8B EC                mov         ebp,esp  
013C39C3 81 EC CC 00 00 00    sub         esp,0CCh  
013C39C9 53                   push        ebx  
013C39CA 56                   push        esi  
013C39CB 57                   push        edi  
013C39CC 51                   push        ecx                       <span style="color:#009900;">/* 保存現場 ,後面的填充0xCC會用到ecx */</span>
013C39CD 8D BD 34 FF FF FF    lea         edi,[ebp+FFFFFF34h]  
013C39D3 B9 33 00 00 00       mov         ecx,33h  
013C39D8 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
013C39DD F3 AB                rep stos    dword ptr es:[edi]  
013C39DF 59                   pop         ecx  
013C39E0 89 4D F8             mov         dword ptr [ebp-8],ecx  
    12: 		printf("%d\n",x+y+a+b) ;
013C39E3 8B 45 F8             mov         eax,dword ptr [ebp-8]     <span style="color:#009900;">/***************</span>
013C39E6 8B 08                mov         ecx,dword ptr [eax]        <span style="color:#009900;">*</span>
013C39E8 8B 55 F8             mov         edx,dword ptr [ebp-8]      <span style="color:#009900;">* 函數核心功能</span>
013C39EB 03 4A 04             add         ecx,dword ptr [edx+4]      <span style="color:#009900;">*</span>
013C39EE 03 4D 08             add         ecx,dword ptr [ebp+8]      <span style="color:#009900;">*</span>
013C39F1 03 4D 0C             add         ecx,dword ptr [ebp+0Ch]  <span style="color:#009900;">  ***************/</span>
013C39F4 8B F4                mov         esi,esp  
013C39F6 51                   push        ecx  
013C39F7 68 A8 58 3C 01       push        13C58A8h  
013C39FC FF 15 B8 92 3C 01    call        dword ptr ds:[013C92B8h]  
013C3A02 83 C4 08             add         esp,8  
013C3A05 3B F4                cmp         esi,esp  
013C3A07 E8 D4 D7 FF FF       call        013C11E0 
    13:     }
00393A0C 5F                   pop         edi  
00393A0D 5E                   pop         esi  
00393A0E 5B                   pop         ebx  
00393A0F 81 C4 CC 00 00 00    add         esp,0CCh  
00393A15 3B EC                cmp         ebp,esp  
00393A17 E8 C4 D7 FF FF       call        003911E0  
00393A1C 8B E5                mov         esp,ebp  
00393A1E 5D                   pop         ebp  
00393A1F C2 08 00             ret         8                          <span style="color:#009900;">/* 平衡堆棧(被調用者平衡堆棧) */</span>

 


/************************************************************

*

<span style="color:#009900;">* haha.Plus(3,4)函數內部(即__thiscall調用方式)
</span>

*

************************************************************/

    17: void Plus(int a,int b)
    18: {
00393420 55                   push        ebp  
00393421 8B EC                mov         ebp,esp  
00393423 81 EC C0 00 00 00    sub         esp,0C0h  
00393429 53                   push        ebx  
0039342A 56                   push        esi  
0039342B 57                   push        edi  
0039342C 8D BD 40 FF FF FF    lea         edi,[ebp+FFFFFF40h]  
00393432 B9 30 00 00 00       mov         ecx,30h  
00393437 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
0039343C F3 AB                rep stos    dword ptr es:[edi]  
    19: 	printf("%d\n",1+2+a+b) ;
0039343E 8B 45 0C             mov         eax,dword ptr [ebp+0Ch]  
00393441 8B 4D 08             mov         ecx,dword ptr [ebp+8]  
00393444 8D 54 01 03          lea         edx,[ecx+eax+3]  
00393448 8B F4                mov         esi,esp  
0039344A 52                   push        edx  
0039344B 68 A8 58 39 00       push        3958A8h  
00393450 FF 15 B8 92 39 00    call        dword ptr ds:[003992B8h]  
00393456 83 C4 08             add         esp,8  
00393459 3B F4                cmp         esi,esp  
0039345B E8 80 DD FF FF       call        003911E0  
    20: }
00393460 5F                   pop         edi  
00393461 5E                   pop         esi  
00393462 5B                   pop         ebx  
00393463 81 C4 C0 00 00 00    add         esp,0C0h  
00393469 3B EC                cmp         ebp,esp  
0039346B E8 70 DD FF FF       call        003911E0  
00393470 8B E5                mov         esp,ebp  
00393472 5D                   pop         ebp  
00393473 C3                   ret                                <span style="color:#009900;"> /* 直接返回 , 並沒有在被調用函數內部平衡堆棧 */</span>
 




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章