4-01-(C++类 this指针)

结构体传参,传递的是副本

结构体里面写函数,结构体的大小不变

函数的地址不在结构体里面。

类里面的函数都要传一个this指针,即

lea         ecx,[s]  

普通的函数结构体传参

this指针的特点

1、你用或者不用,它就在那里
2、参数个数确定的时候,用ecx来传递
3、参数个数不确定的时候,最后一个传递(参见不定长参数)
4this指针不能做++ -- 等运算,不能重新被赋值.
5this指针不占用结构体的宽度.

类的函数传参与普通函数的传参

struct st
{
	int x;
	int y;

	st(int x, int y)
	{
		this->x = x;
		this->y = y;
	}

	int Add()
	{
		return this->x + this->y;
	}
	int Sub()
	{
		return this->x - this->y;
	}
	int Mul()
	{
		return this->x * this->y;
	}
	int Div()
	{
		return this->x / this->y;
	}
};
s.Add();
008F460B 8D 4D F0             lea         ecx,[s]  
008F460E E8 D0 CD FF FF       call        st::Add (08F13E3h)

008F2F40 55                   push        ebp  
008F2F41 8B EC                mov         ebp,esp  
008F2F43 81 EC CC 00 00 00    sub         esp,0CCh  
008F2F49 53                   push        ebx  
008F2F4A 56                   push        esi  
008F2F4B 57                   push        edi  
008F2F4C 51                   push        ecx  
008F2F4D 8D 7D F4             lea         edi,[ebp-0Ch]  
008F2F50 B9 03 00 00 00       mov         ecx,3  
008F2F55 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
008F2F5A F3 AB                rep stos    dword ptr es:[edi]  
008F2F5C 59                   pop         ecx  
008F2F5D 89 4D F8             mov         dword ptr [this],ecx  
008F2F60 B9 66 C0 8F 00       mov         ecx,offset _570D0804_main@cpp (08FC066h)  
008F2F65 E8 B6 E3 FF FF       call        @__CheckForDebuggerJustMyCode@4 (08F1320h)  
return this->x + this->y;
008F2F6A 8B 45 F8             mov         eax,dword ptr [this]  
008F2F6D 8B 00                mov         eax,dword ptr [eax]  
008F2F6F 8B 4D F8             mov         ecx,dword ptr [this]  
008F2F72 03 41 04             add         eax,dword ptr [ecx+4]
//ecx就是this指针,指向结构体第一个成员

普通函数

Add(&s);
005052CB 8D 45 F0             lea         eax,[s]  
005052CE 50                   push        eax  
005052CF E8 05 C1 FF FF       call        Add (05013D9h)  
005052D4 83 C4 04             add         esp,4  

005017D0 55                   push        ebp  
005017D1 8B EC                mov         ebp,esp  
005017D3 81 EC C0 00 00 00    sub         esp,0C0h  
005017D9 53                   push        ebx  
005017DA 56                   push        esi  
005017DB 57                   push        edi  
005017DC 8B FD                mov         edi,ebp  
005017DE 33 C9                xor         ecx,ecx  
005017E0 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
005017E5 F3 AB                rep stos    dword ptr es:[edi]  
005017E7 B9 66 C0 50 00       mov         ecx,offset _570D0804_main@cpp (050C066h)  
005017EC E8 2F FB FF FF       call        @__CheckForDebuggerJustMyCode@4 (0501320h)  
    35: 	return s->x + s->y;
005017F1 8B 45 08             mov         eax,dword ptr [s]  
005017F4 8B 00                mov         eax,dword ptr [eax]  
005017F6 8B 4D 08             mov         ecx,dword ptr [s]  
005017F9 03 41 04             add         eax,dword ptr [ecx+4]  
    36: }
005017FC 5F                   pop         edi  
005017FD 5E                   pop         esi  
005017FE 5B                   pop         ebx  
005017FF 81 C4 C0 00 00 00    add         esp,0C0h  
00501805 3B EC                cmp         ebp,esp  
00501807 E8 38 FA FF FF       call        __RTC_CheckEsp (0501244h)  
0050180C 8B E5                mov         esp,ebp  
0050180E 5D                   pop         ebp  
0050180F C3                   ret  

普通函数外平栈,即调用约定为cdcall

类的函数内平栈,即调用约定为stdcall

空结构体的大小

为一

image-20241201120931944

作业

1、设计一个结构体,有两个Int类型的成员X,Y 在结构体内部定义4个函数							
							
分别实现对X Y的加法、减法、乘法与除法的功能.							
							
2、观察这些函数调用的时候,与其他的函数调用有哪些不同?							
							
从参数传递、压栈顺序、堆栈平衡来总结.							
							
3、空结构体的大小是多少?为什么?							


4、下面代码能否执行?						
						
struct Person  						
{  						
    void Fn_1()						
	{					
		printf("Person:Fn_1()\n");				
	}					
    void Fn_2() 						
	{					
		printf("Person:Fn_2()%x\n");				
	}					
};  						
						
int main(int argc, char* argv[])						
{						
						
	Person* p = NULL;					
	p->Fn_1();					
	p->Fn_2();					
						
	return 0;					
}						
						
4、下面代码能否执行?						
						
						
struct Person  						
{  						
	int x ;					
    void Fn_1()						
	{					
		printf("Person:Fn_1()\n");				
	}					
    void Fn_2() 						
	{					
		x = 10;				
		printf("Person:Fn_2()%x\n");				
	}					
};  						
  						
						
int main(int argc, char* argv[])						
{						
	Person* p = NULL;					
						
	p->Fn_1();					
	p->Fn_2();					
						
	return 0;					
}						

调用成员函数add反汇编
39:       t.add();
00401084 8D 4D F8             lea         ecx,[ebp-8]					*
00401087 E8 79 FF FF FF       call        @ILT+0(St::add) (00401005)

00401100 55                   push        ebp
00401101 8B EC                mov         ebp,esp
00401103 83 EC 44             sub         esp,44h
00401106 53                   push        ebx
00401107 56                   push        esi
00401108 57                   push        edi
00401109 51                   push        ecx							*
0040110A 8D 7D BC             lea         edi,[ebp-44h]
0040110D B9 11 00 00 00       mov         ecx,11h
00401112 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401117 F3 AB                rep stos    dword ptr [edi]
00401119 59                   pop         ecx							*
0040111A 89 4D FC             mov         dword ptr [ebp-4],ecx			  *这里将结构体的指针传入函数栈帧中
14:           return this->X+this->Y;
0040111D 8B 45 FC             mov         eax,dword ptr [ebp-4]
00401120 8B 00                mov         eax,dword ptr [eax]
00401122 8B 4D FC             mov         ecx,dword ptr [ebp-4]
00401125 03 41 04             add         eax,dword ptr [ecx+4]
15:       }
00401128 5F                   pop         edi
00401129 5E                   pop         esi
0040112A 5B                   pop         ebx
0040112B 8B E5                mov         esp,ebp
0040112D 5D                   pop         ebp
0040112E C3                   ret
posted @   悠悠悠key  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示