C++函数调用之thiscall
2015-09-09 20:20
627 查看
C++函数调用之thiscall
所有c++对象共享类中的一份代码拷贝,那c++是怎么实现对每个对象的数据的正确操作?
这就要归功与c++的thiscall, C++会为每个类成员函数传递一个this指针即指向被操作对象的地址做为成员函数的隐含参数(被static修饰的除外 ),VC下编译器在调用非static函数时会把这个指针放入ecx寄存器,,,,,,
下面让我们来看看thiscall在c++中到底是怎么实现的,,,
有如下代码
![](https://img-blog.csdn.net/20150909201637803?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
查看反汇编代码
![](https://img-blog.csdn.net/20150909201645259?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
发现在调用构造函数与fadd函数之前有lea ecx,[ebp-4]指令
那么这条指令有什么用?
[ebp-4]这个内存单元存放的是什么?
首先让我们来解答第二个问题
从反汇编代码中我们可以看到在第17行以后的三条指令是实例化一个对象
所以[ebp-4]这个单元的地址就是编译器为对象a分配的栈空间的首地址(单单的[ebp-4]没有什么意义,仅仅取得它的地址也没什么意义,在于怎么使用它,,,);
而lea ecx,[ebp-4]表示把对象a的地址放入ecx寄存器
好下面来让我们解决第一个问题
从第一个问题的解答我们知道ecx存放的是对象的地址,所以ecx中的值就是c++中所谓的this指针,所以lea ecx,[ebp-4]就是为成员函数传递this指针的,现在这个指针是没有什么意义,它代表指向从此地址起的所有空间
下面让我们进入fadd函数内部查看其反汇编代码
![](https://img-blog.csdn.net/20150909202406345?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
我们来跟踪下ecx寄存器的使用情况
Push ecx 把ecx(this)的值压栈
mov ecx,11h 把ecx当作计数器使用
pop ecx 把值(this)从栈中弹到exc中
mov dword ptr [ebp-4],ecx 把ecx值(this)放到成员函数的栈中
到此ecx的任务已经完成了
下面让我们看下成员函数到底是怎样去引用一个对象的成员变量的
首先把[ebp-4] (this) 放入eax
然后mov ecx,dword ptr [eax] 指令(dword的修饰让对此地址的使用变的有意义)到this指针(eax寄存器的值)指向的地址取四个字节即成员变量a(编译器只为对象分配存放成员变量与虚表指针的空间),放到ecx寄存器中,然后add ecx,1 (a+1)
最后mov edx,dword ptr [ebp-4]把this指针放到edx中,mov dword ptr [edx],ecx 把ecx的值(a+1)放到this指针(edx的值)指向的内存中(即成员变量a中)
到此成员函数已经正确引用到了成员变量
所有c++对象共享类中的一份代码拷贝,那c++是怎么实现对每个对象的数据的正确操作?
这就要归功与c++的thiscall, C++会为每个类成员函数传递一个this指针即指向被操作对象的地址做为成员函数的隐含参数(被static修饰的除外 ),VC下编译器在调用非static函数时会把这个指针放入ecx寄存器,,,,,,
下面让我们来看看thiscall在c++中到底是怎么实现的,,,
有如下代码
查看反汇编代码
发现在调用构造函数与fadd函数之前有lea ecx,[ebp-4]指令
那么这条指令有什么用?
[ebp-4]这个内存单元存放的是什么?
首先让我们来解答第二个问题
从反汇编代码中我们可以看到在第17行以后的三条指令是实例化一个对象
所以[ebp-4]这个单元的地址就是编译器为对象a分配的栈空间的首地址(单单的[ebp-4]没有什么意义,仅仅取得它的地址也没什么意义,在于怎么使用它,,,);
而lea ecx,[ebp-4]表示把对象a的地址放入ecx寄存器
好下面来让我们解决第一个问题
从第一个问题的解答我们知道ecx存放的是对象的地址,所以ecx中的值就是c++中所谓的this指针,所以lea ecx,[ebp-4]就是为成员函数传递this指针的,现在这个指针是没有什么意义,它代表指向从此地址起的所有空间
下面让我们进入fadd函数内部查看其反汇编代码
我们来跟踪下ecx寄存器的使用情况
Push ecx 把ecx(this)的值压栈
mov ecx,11h 把ecx当作计数器使用
pop ecx 把值(this)从栈中弹到exc中
mov dword ptr [ebp-4],ecx 把ecx值(this)放到成员函数的栈中
到此ecx的任务已经完成了
下面让我们看下成员函数到底是怎样去引用一个对象的成员变量的
首先把[ebp-4] (this) 放入eax
然后mov ecx,dword ptr [eax] 指令(dword的修饰让对此地址的使用变的有意义)到this指针(eax寄存器的值)指向的地址取四个字节即成员变量a(编译器只为对象分配存放成员变量与虚表指针的空间),放到ecx寄存器中,然后add ecx,1 (a+1)
最后mov edx,dword ptr [ebp-4]把this指针放到edx中,mov dword ptr [edx],ecx 把ecx的值(a+1)放到this指针(edx的值)指向的内存中(即成员变量a中)
到此成员函数已经正确引用到了成员变量