Wednesday, February 11, 2009

How G++ implement virtual function

Introduction

    We know that virtual function in C++ is implemented by VPTR. And there is a pointer in the beginning of every instance of the Class point to the VPTR table. That means VPTR table is sole in the process and every instance share the same VPTR.

    When the virtual function is called in program, this pointer pass to the virtual function as the first parameter.(all the non-static function of the class use the same call method) The function can know which instance is used.

    It's clear and simple. But how the whole mechanism is implemented in machine code or assemble code.

    Let's begin our fascinating journey by a little example:

class A{

public:

virtual void test( ){i = 0;};

int i;

};

class B: public A{

public:

virtual void test(){i=1976;};

};

void tv(A* p)

{

p->test();

}

int main()

{

B b;

tv(&b);

}

The example do nothing, only set the class attribute i to 1976.

We can generate assemble code by a option -S, “g++ vptr.cpp -S�.

Let's check the assemble code in two parts:

  1. How to instance b?

  2. How virtual function is called?

First part, How to instant b?

In the main function, after push esp, init ebp , the program do the following thing.

subl $20, %esp

leal -12(%ebp), %eax

movl %eax, (%esp)

call _ZN1BC1Ev

What's that mean? Let me explain it instruction by instruction.

First instruction subtitude esp by 20, it will reserve 20 bytes for local variable. You may ask rith now, the size of B is only 8 bytes, including VPTR pointer and an int i, why do GCC reserve 20 bytes. Beats me, Except the 8 bytes, there are 12 bytes left. Who need them? The answer is call stack and return value. In next two instructions, it's function will displayed.

“leal� and “movl� instrunciton assign the instance b's memory and make preparation for call the constructor of B. After this two instructions, the stack illustrated as below diagram.

Let's enter the construction of _ZN1BC1Ev:

pushl %ebp

movl %esp, %ebp.

subl $8, %esp

movl 8(%ebp), %eax

movl %eax, (%esp)

call _ZN1AC2Ev

movl $_ZTV1B+8, %edx

movl 8(%ebp), %eax

movl %edx, (%eax)

leave

retB,

We skip A's constructor because they are same as call B's constructor. The first instructor after “call _ZN1AC2Ev� is a movl instructor. The _ ZTV1B is the VPTR table. It is defined in code:

_ZTV1B:

.long 0

.long _ZTI1B

.long _ZN1B4testEv

_ZTV1B+8 is the virtual function test address. This instruction would move the VPTR's address to register edx. The next two instruction will init the class's VPTR pointer, put the VPTR's address into the pointer's value. Then the construction is completed. The later leave instruction will move EBP's value and pop EBP from the stack.

The Second Part: How virtual function is called?

Let's watch the assemble code of function tv:

The two instructions before the tv is called are very clear. They are function tv's parameter.

leal -12(%ebp), %eax

movl %eax, (%esp)

call _Z2tvP1A

Let's enter function tv directly.

pushl %ebp

movl %esp, %ebp

subl $8, %esp

movl 8(%ebp), %eax

movl (%eax), %eax

movl (%eax), %edx

movl 8(%ebp), %eax

movl %eax, (%esp)

call *%edx

leave

ret

I'll skip the first three instructions, they are all same in each function. After the instruction,movl 8(%ebp), %eax , register eax's value is the address of variable b. After the instruction, movl (%eax), %eax, register eax value is the address of VPTR. After the instruction,movl (%eax), %edx, register edx value is the virtual function's address. The next three instruction is calling the virtual function.

Then all is done. It's simple, right?

Monday, February 2, 2009

Plan for 2009

1. Develop my English(Oral,Listening, writing).

   1.1 read one Grimm’s fairy tale everyday.

   1.2 watch Friends.

   1.3 recite Family Album USA and New Concept English 3,4

   1.4 listen to CRI(FM91.7) everyday.     

2. Develop knowledge of Android and linux kernel( or minix kernel)

   2.1 Master Binder.

   2.2 Master how to write linux driver

   2.3 learn SVG engine. 

3. Strengthen the ability of communication, to express myself and persuading others.

4. Attend Ielts examination.

5. Travel twice at least.

    5.1 go to Ziyuan in the spring.

    5.2 go to Tibet in the summer.

6. develop my tennis skills.

    6.1 pratice tennis every week.

7. Read China News week and an IT related magzine.

8. Buy an apartment.

9. make new friends and extend my social circle.

10. Exercise every week.

Plan for my Chinese New Year holiday

1. relax from Jan 24 to Jan 26

2. Go to Ditan temple fair and take photos

   There are too much people in Ditan, I give up.

3. go to ski twice

    3.1 learn wedge turn

    3.2 learn Stem Christi turn

4. setup the enviroment of android.

5. learn binder

6. learn how text is draw in svg engine.

The Stautus of my plan for 2008

1. Travel to HuangShan Mountain in Spring. Travel to Tibet in summer

Half done. I go to Nanjing, HangZhou and Huangshan(with a friend from India) in the fall. But I don’t go to Tibet.

2. Develop my Oral English

Half Done. I work with India guys for several month. And make friends with all of them. I like them and enjoy India food :)

3. Develop my kernel knowledge

None.

4. Write technical blog as much as possible.

None

5. Develop my tennis skills.

Done. I play much in 2008

6. Get 6.5 score in Ielts

None.

7. Learn riding

Half done. I attend 6 hour training class.

8. Take my parents to travel.

None. But I want to do this at Chinese New Year.

And My extra bonus

1. I get two award. :D, not much in amount, but I’m very happy.

2. Lead fl bug fix in the second half the year. I get some experence of leading a large component, The price is work overtime for 5 month.

3. Convert to employee. After my converting, the fire storm begins at company, all the contractor will leave. I don’t know it’s a good thing or not.

4. Attend a blind date.

5. Buy a Pentax k100D.