this指针与__thiscall调用方式

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/jxz_dz/article/details/47814405

__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>
 




猜你喜欢

转载自blog.csdn.net/jxz_dz/article/details/47814405