virtual functiona and assembly code

This is a discussion on virtual functiona and assembly code within the C++ Programming forums, part of the General Programming Boards category; I'm trying to get basic understanding of what is going on "behind the scene" with virtual methods and VPRT. In ...

  1. #1
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    712

    virtual functiona and assembly code

    I'm trying to get basic understanding of what is going on "behind the scene"
    with virtual methods and VPRT.

    In visual studio .net I see this code:
    fun(d);

    00432416 lea eax,[d]
    00432419 push eax
    0043241A call fun (42FEB4h)
    0043241F add esp,4

    I'm interpreting this like:
    first place adress of d into register eax
    then push contents of eax (adress of d) on stack
    call function on adress (42FEB4h) which is probably adress of function f()
    then increment stack pointer

    Then program flow is moving (I don't know before 0043241F add esp,4 or after it)

    in void fun(Base& b)

    among other code there are:
    b.f(1);
    0043130E mov esi,esp
    00431310 push 1
    00431312 mov eax,dword ptr [b]
    00431315 mov edx,dword ptr [eax]
    00431317 mov ecx,dword ptr [b]
    0043131A call dword ptr [edx]
    0043131C cmp esi,esp
    0043131E call @ILT+6220(__RTC_CheckEsp) (42E851h)



    this means:
    place contents of stack pointer in register esi I think it must be adress of d, but that add esp,4 in previous is enigma
    push argument 1,
    the rest is pretty much confuse for me ptr[b] ... where is VPRT here?
    maybe I should see this as:

    place adress of b in eax register
    place adress (!?!) eax in register edx
    again place adress of b only this time in ecx

    And then two there are call. I'd like to understand this

    so if there are among you guys some C++/assembly master

    who can explain this step by step like I tried I'd be gratefull.

    Thanks!

    And the complete code is:
    Code:
    #include <iostream>
    using namespace std;
    
    class Base
    {
    	int data;
    public:
    	virtual void f(int){}
    
    };
    class Derived : public Base
    {
    	int date;
    public:
    	void f(int)
    	{
    		cout<<"derived"<<endl;
    	}
    };
    void fun(Base& b)
    {
    	b.f(1);
    }
    int main()
    {
    	Derived d;
    	fun(d);
    }
    Last edited by Micko; 02-28-2004 at 05:31 AM.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,673
    I'm no assembly guru but I can tell you what's going on.
    First thing you'll want to know are the different calling conventions. The call to fun() uses the __cdecl calling convention. When calling member functions, the "thiscall" calling convention is used.
    (Notice the above link is "Microsoft Specific", other compilers may implement "thiscall" differently)

    The next thing you need to know is the following: (I'm quoting from this article)
    From MSDN:
    The memory image of an instance of a class has one pointer to the vtable of this class, stored in front of the actual data members of the object. Thus an object that uses virtual functions occupies 4 additional bytes for each instance. The vtable itself occupies 4 bytes for each virtual function, but there is only one vtable per class and it is shared by all instances. When you invoke a virtual function from a base class, the C++ compiler has a pointer to the object's instance data (the "this" pointer). It obtains the pointer to the vtable of the class from the first 4 bytes of the object's instance data. Each virtual function has a unique index in the vtable of a given class. The compiler simply obtains the function address from the vtable at the function's index and branches to this address. When you invoke calls through a pointer to the base class, the technique is the same.
    Now we know enough to atleast guess what these lines are doing:
    Code:
    00431312 mov eax,dword ptr [d]   //load "this" into eax
    00431315 mov edx,dword ptr [eax] //load vtable pointer into edx
    00431317 mov ecx,dword ptr [d]   //load "this" into ecx (see "thiscall" calling convention)
    0043131A call dword ptr [edx]    //vtable has a single entry, f(), at index 0
    gg

  3. #3
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    712
    Thanks man!
    I have learned more using this forum then using many books!

Popular pages Recent additions subscribe to a feed

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21