有许多C++的技术资料特意指出,C++语言使用THISCALL调用方式,在X86架构上,会使用ECX寄存器传递this指针。真的是这样吗?
产生出的中间文件“main.s"就是相应的汇编代码。
为了找到this指针,编写如下C++程序(main.cpp):
#include <stdio.h>
class A
{
public:
int m_Num;
A(void)
:m_Num(0xAB)
{
}
virtual void Func_F(void)
{
}
virtual void Func_G(void)
{
}
};
class B: public A
{
public:
virtual void Func_F(void)
{
int rCX = 0, rAX=0, rEBP8=0;
printf("this=0x%X\n", this);
asm volatile
(
"movl %%ecx,%0\n\t"
"movl %%eax,%1\n\t"
"movl 8(%%ebp),%2\n\t"
: "=r"(rCX), "=r"(rAX),"=r"(rEBP8)
: "r"(rCX), "r"(rAX),"r"(rEBP8)
: /* */
);
printf("Cur ECX=[0x%X] EAX=[0x%X] esp8=[0x%X] this=[0x%X]\n", rCX, rAX, rEBP8,this);
}
};
int main(int args, char ** argv)
{
B * pB = new B;
pB->Func_F();
return 0;
}
函数Func_F会打印出当前的ECX的数值和this指针的数值, 其中ECX的数值通过内嵌汇编语言获取的,在Linux(Fedora 10) X86系统上使用G++编译
g++ -o test main.cpp
运行编译出的test文件,输出结果如下:
[yfeng@work work]$ ./test
this=0x9C40008
Cur ECX=[0xBF80A5F8] EAX=[0x0] esp8=[0x9C40008] this=[0x9C40008]
从输出结果可以很明显的看到,this指针并没有存放到ECX里面,而是放在堆栈(ESP+8),(ESP+8)正是函数Func_F的第一个参数存放地址,可见类的this指针是作为第一个参数传递给函数的。读者可以使用G++产生的汇编代码进行深入研究, 使用
g++ -s -save-temps main.cpp
产生出的中间文件“main.s"就是相应的汇编代码。
结论: 可见,读书不能尽信书,其中道理需要自己反复实践和体会。
声明:这里并不是说所有编译器都会把this作为第一个参数传递,其它编译器或者同一编译器的不同版本也许使用其它方法传递this指针。