从反汇编看this指针

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

在这大概从三个角度来谈this指针 :

A . this指针的由来  B . this指针的特点   C . this指针与this Call调用方式   

有错误的地方,欢迎批评指正大笑大笑

A . this指针的由来

     测试代码 1: 

#include "stdafx.h"

struct MyStruct
{
    int x ;
    int y ;
};

//函数在结构体外部
void Max(MyStruct* str)
{
    if (str->x > str->y)
        printf("%d",str->x);
    else
        printf("%d",str->y);
}
int _tmain(int argc, _TCHAR* argv[])
{
    MyStruct haha ;
    haha.x = 1 ;
    haha.y = 2 ;
    Max(&haha);
    printf("%d\n",sizeof(haha));
    return 0;
}  

执行结果 : 2   8

测试代码 2:

#include "stdafx.h"

struct MyStruct
{
	int x ;
	int y ;
	//函数在结构体内部
	int Max(MyStruct* str)
	{
		return str->x > str->y ? str->x :str->y ;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	MyStruct haha ;
	haha.x = 1 ;
	haha.y = 2 ;
        haha.Max(&haha);
        printf("%d\n",haha.Max(&haha));
	printf("%d\n",sizeof(haha));
	return 0;
}

执行结果 : 2   8


由此可以看出函数在结构体内部与外部并不影响对象(或者结构体变量)的大小 , 那么这就构成了类的原因之一.  然而这并不是关键

测试代码1 的反汇编代码

<pre name="code" class="cpp">    23: 	MyStruct haha ;
    24: 	haha.x = 1 ;
011739E8 C7 45 F0 01 00 00 00 mov         dword ptr [ebp-10h],1  
    25: 	haha.y = 2 ;
011739EF C7 45 F4 02 00 00 00 mov         dword ptr [ebp-0Ch],2  
    26: 	Max(&haha);
011739F6 8D 45 F0             lea         eax,[ebp-10h]  
011739F9 50                   push        eax  
011739FA E8 FF D7 FF FF       call        011711FE  
011739FF 83 C4 04             add         esp,4  

 
  

//进入函数内部(部分):     
    13: void Max(MyStruct* str)
    14: {
011E2A20 55                   push        ebp  
011E2A21 8B EC                mov         ebp,esp  
011E2A23 81 EC C0 00 00 00    sub         esp,0C0h  
011E2A29 53                   push        ebx  
011E2A2A 56                   push        esi  
011E2A2B 57                   push        edi  
011E2A2C 8D BD 40 FF FF FF    lea         edi,[ebp+FFFFFF40h]  
011E2A32 B9 30 00 00 00       mov         ecx,30h  
011E2A37 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
011E2A3C F3 AB                rep stos    dword ptr es:[edi]  
    15: 	if (str->x > str->y)
011E2A3E 8B 45 08             mov         eax,dword ptr [ebp+8]  
011E2A41 8B 4D 08             mov         ecx,dword ptr [ebp+8]  
011E2A44 8B 10                mov         edx,dword ptr [eax]  
011E2A46 3B 51 04             cmp         edx,dword ptr [ecx+4]  
011E2A49 7E 1F                jle         011E2A6A  
    16: 		printf("%d\n",str->x);



测试代码2的反汇编代码:
    22:     MyStruct haha ;
    23:     haha.x = 1 ;
00F939E8 C7 45 F0 01 00 00 00 mov         <span style="background-color: rgb(51, 255, 255);">dword ptr [ebp-10h],1 </span>
    24:     haha.y = 2 ;
00F939EF C7 45 F4 02 00 00 00 mov         dword ptr [ebp-0Ch],2  
    25:     haha.Max(&haha);
00F939F6 8D 45 F0             lea         eax,[ebp-10h]  
00F939F9 50                   push        eax  
00F939FA 8D 4D F0             <span style="background-color: rgb(255, 255, 51);">lea         ecx,[ebp-10h] </span>
00F939FD E8 01 D8 FF FF       call        00F91203  

    10: 	//函数在结构体内部
    11: 	void Max(MyStruct* str)
    12: 	{
00F93420 55                   push        ebp  
00F93421 8B EC                mov         ebp,esp  
00F93423 81 EC CC 00 00 00    sub         esp,0CCh  
00F93429 53                   push        ebx  
00F9342A 56                   push        esi  
00F9342B 57                   push        edi  
00F9342C 51                   <span style="background-color: rgb(255, 255, 51);">push        ecx</span>  
00F9342D 8D BD 34 FF FF FF    lea         edi,[ebp+FFFFFF34h]  
00F93433 B9 33 00 00 00       mov         ecx,33h  
00F93438 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
00F9343D F3 AB                rep stos    dword ptr es:[edi]  
00F9343F 59                   <span style="background-color: rgb(255, 255, 51);">pop         ecx</span>  
00F93440 89 4D F8            <span style="background-color: rgb(255, 255, 51);"> mov         dword ptr [ebp-8],ecx</span>  
    13: 		if (str->x > str->y)
00F93443 8B 45 08             mov         eax,dword ptr [ebp+8]  
00F93446 8B 4D 08             mov         ecx,dword ptr [ebp+8]  
00F93449 8B 10                mov         edx,dword ptr [eax]  
00F9344B 3B 51 04             cmp         edx,dword ptr [ecx+4]  
00F9344E 7E 1F                jle         00F9346F  
    14: 			printf("%d\n",str->x);

 
  

可以注意到 测试代码2的反汇编代码  在call 之前多了一句代码 

<pre name="code" class="cpp"><span style="background-color: rgb(255, 255, 0);">lea         eax,[ebp-10h]</span>
 
  

在函数内部我们可以观察到ecx的值被存放到dword ptr [ebp-8] 的位置 ,即为参数 .

那么[ebp-10h]是什么呢 ,这显然是一个地址 , 是什么地址呢?  在上面代码中可知

[ebp-10h]存放的是 结构体变量(在C++中就称为对象了)的 第一个成员变量的地址 .这就是所谓的this指针了

但是呢,问题来了: 在C语言代码中我们什么都没做,只是将函数放在了结构体内部 . 就莫名其妙的多出了汇编指令

<pre name="code" class="cpp"><pre name="code" class="cpp"><span style="background-color: rgb(255, 255, 0);">lea         eax,[ebp-10h]</span>
 
  
 
  

由此,我们得出结论 : 将全局的函数放进结构体内,便出现了this指针,该this指针是由ecx传递的 . 更重要的是这是编译器替我们加上的.

即是说,由C转化为C++,更多的是编译器做的操作.

可以归纳this指针的本质 :

 this是调用结构体(或类)内部成员函数时传递的参数(通常用ecx传递) . 其本质是结构体变量(或者对象)的第一个成员变量的地址.(读者可以试下)

B : this指针的特点

 1.this指针不可以++ - -操作 , 即this指针的值不可以被改变 .

 2.参数个数确定的函数,this指针是由ecx传递的 , 在变参函数中最后一个传递的参数是this指针

 3.this指针不占用结构体变量(类的对象)的大小

C : this指针与this调用方式

见下篇 .



猜你喜欢

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