撥雲見日-尋找C++的this指針

有許多C++的技術資料特意指出,C++語言使用THISCALL調用方式,在X86架構上,會使用ECX寄存器傳遞this指針。真的是這樣嗎?

爲了找到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指針。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章