当前位置:网站首页>The underlying mechanism of the class
The underlying mechanism of the class
2022-08-05 05:05:00 【Chicken Island~】
提出问题:
- Why class function calling convention must bethis call
- 为什么静态成员函数没有this指针
- 为什么类的静态成员函数不能访问类的非静态成员函数
- Do classes really have constructors?
C++代码
class T {
int hp;
public:
int Add(int a, int b) {
return hp + a + b;
}
};
int main(int count, char** args)
{
T t1;
t1.Add(100, 200);
}
汇编代码
00241034 push 0C8h
00241039 push 64h
0024103B lea ecx,[ebp-4]
0024103E call 00241000
00241000 55 push ebp
00241001 8B EC mov ebp,esp
00241003 51 push ecx
00241004 89 4D FC mov dword ptr [ebp-4],ecx //ecxvalue becomes a local variable
00241007 8B 45 FC mov eax,dword ptr [ebp-4]
0024100A 8B 00 mov eax,dword ptr [eax] //this->hp
0024100C 03 45 08 add eax,dword ptr [ebp+8]
0024100F 03 45 0C add eax,dword ptr [ebp+0Ch]
00241012 8B E5 mov esp,ebp
00241014 5D pop ebp
00241015 C2 08 00 ret 8
设计实验:
when the function is usedthis->hp时,ecxwill be used to store类的首地址
when the function is not usedthis->hp时,ecxwill also be used to store类的首地址
发现规律:当调用类的成员函数的时候,ecxwill store the first address of the class,will then be treated as局部变量来使用
得出结论
_thiscall 是C++中 When accessing a member function of a class Defined function calling convention
(1) 寄存器ecxpointer to store the class
(2) 参数由右到左入栈
(3) 堆栈由 被调用者 负责恢复
All non-static member functions of a class can be usedthis指针,thisA pointer is essentially a pointer in an object through a registerecxto pass into member functions,So member functions in a class access its member variables,through pointers+offset to access the,whether or not explicitly usedthis指针
设计实验
C++代码
class T {
inline static int count;
public:
static int GetCount(int a, int b) {
count++;
return 2;
}
};
int main(int count, char** args)
{
T t1;
t1.GetCount(2, 3);
汇编代码
00D31023 6A 03 push 3
00D31025 6A 02 push 2
00D31027 E8 D4 FF FF FF call T::GetCount (0D31000h)
00D3102C 83 C4 08 add esp,8**
count++;
00A21003 A1 28 31 A2 00 mov eax,dword ptr ds:[00A23128h]
00A21008 83 C0 01 add eax,1
00A2100B A3 28 31 A2 00 mov dword ptr ds:[00A23128h],eax
得出结论:
类的静态成员函数,essentially adopted_cdecl约定
(1)参数由右到左入栈
(2) 由[调用者]restore stack balance
答:Because a static member function of a class is essentially an ordinary function,So no pointer to the object is passed at all,Therefore, it cannot access its member variables.;
The static member variable of the class is essentially equivalent to a global variable,有固定的内存地址,Has nothing to do with class objects,So a static member of a class can be passed without an instance of the class[类::静态成员]access in this form
设计实验:
int hp{
1};
发现规律:
- 当int hp{1}时,The disassembled code calls the constructor,The purpose of the call is to make给hp赋值
- 当int hp 时,Disassembled code doesn't call constructor
得出结论:
类TMost of the time there is no constructor,这是因为C++The standards committee requires every class to have a default constructor.
But an empty constructor actually don't have any meaning,So in some cases the compiler will delete meaningless constructors,这是编译器优化的结果.
原则上来讲,Every class has a default constructor.
提出问题:
- 为什么AIM的大小为8个字节?
- p->Die()is how to ensure that the call isWOLF里面的Die()
class AIM {
public :
int HP;
virtual void Eat() {
std::cout << "AIM" << std::endl;
}
virtual void Die() {
std::cout << "AIM-DIE" << std::endl;
}
};
class WOLF :public AIM{
public:
virtual void Eat() {
std::cout << "WOLF" << std::endl;
}
virtual void Die() {
std::cout << "WOLF-DIE" << std::endl;
}
void Sound() {
std::cout << "aoaoaoaoaoaoao!!!!" << std::endl;
}
};
int main(int count, char** args)
{
AIM* p = new WOLF();
p->Die();
std::cout << sizeof(AIM) << std::endl;
}
猜测+实证:AIMThe class should storea four-byte address,through it you can goaccess the address of a virtual function.Through the following print statement, we can see that the four bytes are placed in theAIM类的首地址
std::cout << p << " " << &p << std::endl;
问题2猜测:调用p->Die()function will be passed存储了WOLFpointer to the address of the virtual function of the class进去,然后计算出对应的虚函数地址
实证:逆向分析
[ebp-4]里面的地址→eax
eaxthe memory address inside前四个字节→edx
[edx+4]这个内存地址的前四个字节→ eax
p->Die();
00D11A5D 8B 45 FC mov eax,dword ptr [p]
00D11A60 8B 10 mov edx,dword ptr [eax]
00D11A62 8B 4D FC mov ecx,dword ptr [p]
00D11A65 8B 42 04 mov eax,dword ptr [edx+4]
00D11A68 FF D0 call eax
发现规律:
- 虚函数的地址will be placed in a virtual table
- 这个虚表的地址会被放在类的首地址,当我们通过指针调用虚函数will pass the virtual table when计算out this address,然后执行
直接构建
std::cout << std::hex << "vtable地址:" << pTable[0] << std::endl;
int* func = (int*)pTable[0];
std::cout << std::hex << "Eat地址:" << func[0] << std::endl;
std::cout << std::hex << "Die地址:" << func[1] << std::endl;
unsigned* eat = (unsigned*)func[1];
__asm {
call eat
}
得出结论
(1)Multiple instances of the same class all point to the same virtual function table
(2)The virtual function table is called only if the virtual function is accessed through a pointer
边栏推荐
猜你喜欢
upload upload pictures to Tencent cloud, how to upload pictures
There are a lot of 4T hard drives remaining, prompting "No space left on device" insufficient disk space
Flutter learning 5-integration-packaging-publish
Qt制作18帧丘比特表白意中人、是你的丘比特嘛!!!
[cesium] 3D Tileset model is loaded and associated with the model tree
Flutter真机运行及模拟器运行
【cesium】Load and locate 3D Tileset
The difference between span tag and p
Application status of digital twin technology in power system
Excel Paint
随机推荐
【cesium】元素高亮显示
Application status of digital twin technology in power system
Talk about 20 common problems in data governance
说说数据治理中常见的20个问题
Structured light 3D reconstruction (1) Striped structured light 3D reconstruction
Flutter learning three-Flutter basic structure and principle
C language - vernacular to understand the original code, inverse code and complement code
【cesium】3D Tileset 模型加载并与模型树关联
"Recursion" recursion concept and typical examples
phone call function
【学习笔记之菜Dog学C】动态内存管理之经典笔试题
LAB Semaphore Implementation Details
Flutter Learning 4 - Basic UI Components
LAB 信号量实现细节
【cesium】Load and locate 3D Tileset
Redis - 13. Development Specifications
dedecms织梦tag标签不支持大写字母修复
Cron(Crontab)--use/tutorial/example
服务器磁盘阵列
LeetCode:1403. 非递增顺序的最小子序列【贪心】