See the c++ member function pointer from the assembly (three)

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

The front from the assembly at the c++ member function pointer (a) and c++ member function pointer from the assembly (two) are either single or multiple inheritance, is ordinary, no discussion of virtual inheritance, here's a look, after the introduction of virtual inheritance, member function pointer what will change.

The c++ source code:

#include <cstdio>
using namespace std;

class Top {
public:
    virtual int get1() {
        return 1;
    }
    virtual int get2() {
        return 2;
    }
};

class Left : virtual public Top {
public:
    virtual int get3() {
        return 3;
    }
    virtual int get4() {
        return 4;
    }
};

class Right : virtual public Top {
public:
    virtual int get5() {
        return 5;
    }
    virtual int get6() {
        return 6;
    }
};

class Bottom : public Left, public Right {
public:
    virtual int get1() {
        return 7;
    }
    virtual int get3() {
        return 8;
    }
    virtual int get5() {
        return 9;
    }
    virtual int get7() {
        return 10;
    }
};



int main() {
    Bottom b;
    Bottom* bp = &b;
    Left* lp = bp;
    Right* rp = bp;
    Top* tp = bp;
    
    /******************************Definition of function pointer**********************/
    int(Top::*tgp1)() = &Top::get1;
    int(Top::*tgp2)() = &Top::get2;
    int(Left::*lgp1)() = &Left::get1;
    int(Left::*lgp2)() = &Left::get2;
    int(Left::*lgp3)() = &Left::get3;
    int(Left::*lgp4)() = &Left::get4;
    int(Right::*rgp1)() = &Right::get1;
    int(Right::*rgp2)() = &Right::get2;
    int(Right::*rgp5)() = &Right::get5;
    int(Right::*rgp6)() = &Right::get6;
    int(Bottom::*bgp1)() = &Bottom::get1;
    int(Bottom::*bgp2)() = &Bottom::get2;
    int(Bottom::*bgp3)() = &Bottom::get3;
    int(Bottom::*bgp4)() = &Bottom::get4;
    int(Bottom::*bgp5)() = &Bottom::get5;
    int(Bottom::*bgp6)() = &Bottom::get6;
    int(Bottom::*bgp7)() = &Bottom::get7;
    
    /****************************The output of a member function pointer size*******************/
    printf("sizeof(tgp1) = %d\n", sizeof(tgp1));
    printf("sizeof(tgp2) = %d\n", sizeof(tgp2));
    printf("\n");
    printf("sizeof(lgp1) = %d\n", sizeof(lgp1));
    printf("sizeof(lgp2) = %d\n", sizeof(lgp2));
    printf("sizeof(lgp3) = %d\n", sizeof(lgp3));
    printf("sizeof(lgp4) = %d\n", sizeof(lgp4));
    printf("\n");
    printf("sizeof(rgp1) = %d\n", sizeof(rgp1));
    printf("sizeof(rgp2) = %d\n", sizeof(rgp2));
    printf("sizeof(rgp5) = %d\n", sizeof(rgp5));
    printf("sizeof(rgp6) = %d\n", sizeof(rgp6));
    printf("\n");
    printf("sizeof(bgp1) = %d\n", sizeof(bgp1));
    printf("sizeof(bgp2) = %d\n", sizeof(bgp2));
    printf("sizeof(bgp3) = %d\n", sizeof(bgp3));
    printf("sizeof(bgp4) = %d\n", sizeof(bgp4));
    printf("sizeof(bgp5) = %d\n", sizeof(bgp5));
    printf("sizeof(bgp6) = %d\n", sizeof(bgp6));
    printf("sizeof(bgp7) = %d\n", sizeof(bgp7));
    printf("\n");
    
    /*********************************The output of various kinds of member function pointer*****************/
    printf("&Top::get1 = %lu\n", &Top::get1);
    printf("&Top::get2 = %lu\n", &Top::get2);
    printf("&Left::get1 = %lu\n", &Left::get1);
    printf("&Left::get2 = %lu\n", &Left::get2);
    printf("&Left::get3 = %lu\n", &Left::get3);
    printf("&Left::get4 = %lu\n", &Left::get4);
    printf("&Right::get1 = %lu\n", &Right::get1);
    printf("&Right::get2 = %lu\n", &Right::get2);
    printf("&Right::get5 = %lu\n", &Right::get5);
    printf("&Right::get6 = %lu\n", &Right::get6);
    printf("&Bottom::get1 = %lu\n", &Bottom::get1);
    printf("&Bottom::get2 = %lu\n", &Bottom::get2);
    printf("&Bottom::get3 = %lu\n", &Bottom::get3);
    printf("&Bottom::get4 = %lu\n", &Bottom::get4);
    printf("&Bottom::get5 = %lu\n", &Bottom::get5);
    printf("&Bottom::get6 = %lu\n", &Bottom::get6);
    printf("&Bottom::get7 = %lu\n", &Bottom::get7);
    
    /********************************A pointer to member function calls with various members*****************/
    (bp->*bgp1)();
    (bp->*bgp2)();
    (bp->*bgp3)();
    (bp->*bgp4)();
    (bp->*bgp5)();
    (bp->*bgp6)();
    (bp->*bgp7)();
    
    
    
    
    
  
}
  

Here is the output:

Through the above output, we can get 2 information:

1 when the class inheritance hierarchy contains a virtual base class, member function pointers programming 12 bytes

2 procedures defined in the 17 member function pointers, but only 3 different address

For the second point, see through the c++ member function pointer from the assembly (a) and c++ member function pointer from the assembly (two) can know, because all member functions with respect to the apparent first address only 3 offset, in the corresponding virtual table 048, therefore, as long as the 3 Vcall function is enough moreover, the function of Vcall is the same, passed through register ECX this pointer, get the first address correctly virtual member function is obtained, then the member function address from the virtual table, and jump to the address implementation. Here are 3 Vcall function assembly code:

??_9Top@@$BA@AE PROC                    ; Top::`vcall'{0}', COMDAT
    mov    eax, DWORD PTR [ecx];Register ECX to save the this pointer, the contents of memory this to which the pointer points (i.e. vftable first address)
                            ;To register eax
    jmp    DWORD PTR [eax];Take eax to save memory address inside the content (virtual address virtual table first address storage), then jump to the address


??_9Top@@$B3AE PROC                    ; Top::`vcall'{4}', COMDAT
    mov    eax, DWORD PTR [ecx];Register ECX to save the this pointer, the contents of memory this to which the pointer points (i.e. vftable first address)
                            ;To register eax
    jmp    DWORD PTR [eax+4];The memory contents from offset eax to save memory address location 4byte (virtual address offset of virtual table first address 4byte memory storage), then jump to the address

??_9Bottom@@$B7AE PROC                    ; Bottom::`vcall'{8}', COMDAT
    mov    eax, DWORD PTR [ecx];Register ECX to save the this pointer, the contents of memory this to which the pointer points (i.e. vftable first address)
                            ;To register eax
    jmp    DWORD PTR [eax+8];The memory contents from offset eax to save memory address location 8byte (virtual address offset of virtual table first address 8byte memory storage), then jump to the address

Below is the Bottom class inheritance graph (diamond inheritance)

Below is the class store layout:

Here to have a look after the introduction of virtual inheritance, a member function pointer is stored is what value.

Assembler code below to see define these members of pointer variable:

60   :     int(Top::*tgp1)() = &Top::get1;

    mov    DWORD PTR _tgp1$[ebp], OFFSET ??_9Top@@$BA@AE ; `vcall'{0}'The memory address?? _9Top@@$BA@AE represents to the tgp1 storage vcall{0} address

; 61   :     int(Top::*tgp2)() = &Top::get2;

    mov    DWORD PTR _tgp2$[ebp], OFFSET ??_9Top@@$B3AE ; Top::`vcall'{4}' With the definition of tgp1

; 62   :     int(Left::*lgp1)() = &Left::get1;

    mov    DWORD PTR $T4213[ebp], OFFSET ??_9Top@@$BA@AE ; Top::`vcall'{0}';The OFFSET?? _9Top@@$BA@AE represented a memory address (vcall{0} address) to the temporary object ST4213 first address memory
    mov    DWORD PTR $T4213[ebp+4], 0;0 to offset the temporary object ST4213 first address 4byte memory
    mov    DWORD PTR $T4213[ebp+8], 4;4 to offset the temporary object ST4213 first address 8byte memory
    mov    ecx, DWORD PTR $T4213[ebp];The temporary object ST4213 first address memory contents to register ECX
    mov    DWORD PTR _lgp1$[ebp], ecx;The ECX register value to the lgp1 first address memory
    mov    edx, DWORD PTR $T4213[ebp+4];To offset temporary object ST4213 first address 4byte memory contents to register EDX
    mov    DWORD PTR _lgp1$[ebp+4], edx;The EDX value for the offset lgp1 first address 4byte memory
    mov    eax, DWORD PTR $T4213[ebp+8];To offset temporary object ST4213 first address 8byte memory contents to register eax
    mov    DWORD PTR _lgp1$[ebp+8], eax;The eax value for the offset lgp1 first address 8byte memory

; 63   :     int(Left::*lgp2)() = &Left::get2;
     ;With the definition of lgp1
    mov    DWORD PTR $T4214[ebp], OFFSET ??_9Top@@$B3AE ; Top::`vcall'{4}'
    mov    DWORD PTR $T4214[ebp+4], 0
    mov    DWORD PTR $T4214[ebp+8], 4
    mov    ecx, DWORD PTR $T4214[ebp]
    mov    DWORD PTR _lgp2$[ebp], ecx
    mov    edx, DWORD PTR $T4214[ebp+4]
    mov    DWORD PTR _lgp2$[ebp+4], edx
    mov    eax, DWORD PTR $T4214[ebp+8]
    mov    DWORD PTR _lgp2$[ebp+8], eax

; 64   :     int(Left::*lgp3)() = &Left::get3;
        ;With the definition of lgp1
    mov    DWORD PTR $T4215[ebp], OFFSET ??_9Top@@$BA@AE ; Top::`vcall'{0}'
    mov    DWORD PTR $T4215[ebp+4], 0
    mov    DWORD PTR $T4215[ebp+8], 0
    mov    ecx, DWORD PTR $T4215[ebp]
    mov    DWORD PTR _lgp3$[ebp], ecx
    mov    edx, DWORD PTR $T4215[ebp+4]
    mov    DWORD PTR _lgp3$[ebp+4], edx
    mov    eax, DWORD PTR $T4215[ebp+8]
    mov    DWORD PTR _lgp3$[ebp+8], eax

; 65   :     int(Left::*lgp4)() = &Left::get4;
         ;With the definition of lgp1

    mov    DWORD PTR $T4216[ebp], OFFSET ??_9Top@@$B3AE ; Top::`vcall'{4}'
    mov    DWORD PTR $T4216[ebp+4], 0
    mov    DWORD PTR $T4216[ebp+8], 0
    mov    ecx, DWORD PTR $T4216[ebp]
    mov    DWORD PTR _lgp4$[ebp], ecx
    mov    edx, DWORD PTR $T4216[ebp+4]
    mov    DWORD PTR _lgp4$[ebp+4], edx
    mov    eax, DWORD PTR $T4216[ebp+8]
    mov    DWORD PTR _lgp4$[ebp+8], eax

; 66   :     int(Right::*rgp1)() = &Right::get1;
       ;With the definition of lgp1
    mov    DWORD PTR $T4217[ebp], OFFSET ??_9Top@@$BA@AE ; Top::`vcall'{0}'
    mov    DWORD PTR $T4217[ebp+4], 0
    mov    DWORD PTR $T4217[ebp+8], 4
    mov    ecx, DWORD PTR $T4217[ebp]
    mov    DWORD PTR _rgp1$[ebp], ecx
    mov    edx, DWORD PTR $T4217[ebp+4]
    mov    DWORD PTR _rgp1$[ebp+4], edx
    mov    eax, DWORD PTR $T4217[ebp+8]
    mov    DWORD PTR _rgp1$[ebp+8], eax

; 67   :     int(Right::*rgp2)() = &Right::get2;
      ;With the definition of lgp1
    mov    DWORD PTR $T4218[ebp], OFFSET ??_9Top@@$B3AE ; Top::`vcall'{4}'
    mov    DWORD PTR $T4218[ebp+4], 0
    mov    DWORD PTR $T4218[ebp+8], 4
    mov    ecx, DWORD PTR $T4218[ebp]
    mov    DWORD PTR _rgp2$[ebp], ecx
    mov    edx, DWORD PTR $T4218[ebp+4]
    mov    DWORD PTR _rgp2$[ebp+4], edx
    mov    eax, DWORD PTR $T4218[ebp+8]
    mov    DWORD PTR _rgp2$[ebp+8], eax

; 68   :     int(Right::*rgp5)() = &Right::get5;
        ;With the definition of lgp1
    mov    DWORD PTR $T4219[ebp], OFFSET ??_9Top@@$BA@AE ; Top::`vcall'{0}'
    mov    DWORD PTR $T4219[ebp+4], 0
    mov    DWORD PTR $T4219[ebp+8], 0
    mov    ecx, DWORD PTR $T4219[ebp]
    mov    DWORD PTR _rgp5$[ebp], ecx
    mov    edx, DWORD PTR $T4219[ebp+4]
    mov    DWORD PTR _rgp5$[ebp+4], edx
    mov    eax, DWORD PTR $T4219[ebp+8]
    mov    DWORD PTR _rgp5$[ebp+8], eax

; 69   :     int(Right::*rgp6)() = &Right::get6;
     ;With the definition of lgp1
    mov    DWORD PTR $T4220[ebp], OFFSET ??_9Top@@$B3AE ; Top::`vcall'{4}'
    mov    DWORD PTR $T4220[ebp+4], 0
    mov    DWORD PTR $T4220[ebp+8], 0
    mov    ecx, DWORD PTR $T4220[ebp]
    mov    DWORD PTR _rgp6$[ebp], ecx
    mov    edx, DWORD PTR $T4220[ebp+4]
    mov    DWORD PTR _rgp6$[ebp+4], edx
    mov    eax, DWORD PTR $T4220[ebp+8]
    mov    DWORD PTR _rgp6$[ebp+8], eax

; 70   :     int(Bottom::*bgp1)() = &Bottom::get1;
     ;With the definition of lgp1
    mov    DWORD PTR $T4221[ebp], OFFSET ??_9Top@@$BA@AE ; Top::`vcall'{0}'
    mov    DWORD PTR $T4221[ebp+4], 0
    mov    DWORD PTR $T4221[ebp+8], 4
    mov    ecx, DWORD PTR $T4221[ebp]
    mov    DWORD PTR _bgp1$[ebp], ecx
    mov    edx, DWORD PTR $T4221[ebp+4]
    mov    DWORD PTR _bgp1$[ebp+4], edx
    mov    eax, DWORD PTR $T4221[ebp+8]
    mov    DWORD PTR _bgp1$[ebp+8], eax

; 71   :     int(Bottom::*bgp2)() = &Bottom::get2;
         ;With the definition of lgp1
    mov    DWORD PTR $T4222[ebp], OFFSET ??_9Top@@$B3AE ; Top::`vcall'{4}'
    mov    DWORD PTR $T4222[ebp+4], 0
    mov    DWORD PTR $T4222[ebp+8], 4
    mov    ecx, DWORD PTR $T4222[ebp]
    mov    DWORD PTR _bgp2$[ebp], ecx
    mov    edx, DWORD PTR $T4222[ebp+4]
    mov    DWORD PTR _bgp2$[ebp+4], edx
    mov    eax, DWORD PTR $T4222[ebp+8]
    mov    DWORD PTR _bgp2$[ebp+8], eax

; 72   :     int(Bottom::*bgp3)() = &Bottom::get3;
         ;With the definition of LG1
    mov    DWORD PTR $T4223[ebp], OFFSET ??_9Top@@$BA@AE ; Top::`vcall'{0}'
    mov    DWORD PTR $T4223[ebp+4], 0
    mov    DWORD PTR $T4223[ebp+8], 0
    mov    ecx, DWORD PTR $T4223[ebp]
    mov    DWORD PTR _bgp3$[ebp], ecx
    mov    edx, DWORD PTR $T4223[ebp+4]
    mov    DWORD PTR _bgp3$[ebp+4], edx
    mov    eax, DWORD PTR $T4223[ebp+8]
    mov    DWORD PTR _bgp3$[ebp+8], eax

; 73   :     int(Bottom::*bgp4)() = &Bottom::get4;
          ;With the definition of lgp1
    mov    DWORD PTR $T4224[ebp], OFFSET ??_9Top@@$B3AE ; Top::`vcall'{4}'
    mov    DWORD PTR $T4224[ebp+4], 0
    mov    DWORD PTR $T4224[ebp+8], 0
    mov    ecx, DWORD PTR $T4224[ebp]
    mov    DWORD PTR _bgp4$[ebp], ecx
    mov    edx, DWORD PTR $T4224[ebp+4]
    mov    DWORD PTR _bgp4$[ebp+4], edx
    mov    eax, DWORD PTR $T4224[ebp+8]
    mov    DWORD PTR _bgp4$[ebp+8], eax

; 74   :     int(Bottom::*bgp5)() = &Bottom::get5;
        ;With the definition of lgp1
    mov    DWORD PTR $T4225[ebp], OFFSET ??_9Top@@$BA@AE ; Top::`vcall'{0}'
    mov    DWORD PTR $T4225[ebp+4], 8
    mov    DWORD PTR $T4225[ebp+8], 0
    mov    ecx, DWORD PTR $T4225[ebp]
    mov    DWORD PTR _bgp5$[ebp], ecx
    mov    edx, DWORD PTR $T4225[ebp+4]
    mov    DWORD PTR _bgp5$[ebp+4], edx
    mov    eax, DWORD PTR $T4225[ebp+8]
    mov    DWORD PTR _bgp5$[ebp+8], eax

; 75   :     int(Bottom::*bgp6)() = &Bottom::get6;
       ;The program are given here only to the execution of assembly code comments
    mov    DWORD PTR $T4226[ebp], OFFSET ??_9Top@@$B3AE ; Top::`vcall'{4}';The?? memory address represented by _9Top@@$B3AE (vcall{4} address) to the first address memory temporary object ST4226
    xor    ecx, ecx;XOR ECX register will be there, this is why the value regardless of ECX, was 0
    jne    SHORT $LN7@main;If the above XOR result is not 0, then jump to label $LN7@main implementation, otherwise, the order of execution, there are sequential execution
    mov    DWORD PTR tv90[ebp], 8;8 to a temporary variable tv90
    jmp    SHORT $LN8@main;Jump to label $LN8@main execution
$LN7@main:
    mov    DWORD PTR tv90[ebp], 0
$LN8@main:
    mov    edx, DWORD PTR tv90[ebp];The temporary variable tv90 values to register EDX
    mov    DWORD PTR $T4226[ebp+4], edx;The I EDX value to offset temporary object ST4226 first address 4byte memory
    mov    DWORD PTR $T4226[ebp+8], 0;0 to offset the temporary object ST4226 first address 8byte memory
    mov    eax, DWORD PTR $T4226[ebp];The temporary object ST4226 first address memory contents to register eax
    mov    DWORD PTR _bgp6$[ebp], eax;The contents of the eax register to the bgp6 first address memory
    mov    ecx, DWORD PTR $T4226[ebp+4];To offset temporary object ST4226 first address 4byte memory contents to register ECX
    mov    DWORD PTR _bgp6$[ebp+4], ecx;The ECX value for the offset bgp6 first address 4byte memory
    mov    edx, DWORD PTR $T4226[ebp+8];To offset temporary object ST4226 first address 8byte memory to register EDX
    mov    DWORD PTR _bgp6$[ebp+8], edx;The EDX value for the offset bgp6 first address 8byte memory

; 76   :     int(Bottom::*bgp7)() = &Bottom::get7;
       ;With the definition of lgp1
    mov    DWORD PTR $T4229[ebp], OFFSET ??_9Bottom@@$B7AE ; Bottom::`vcall'{8}'
    mov    DWORD PTR $T4229[ebp+4], 0
    mov    DWORD PTR $T4229[ebp+8], 0
    mov    eax, DWORD PTR $T4229[ebp]
    mov    DWORD PTR _bgp7$[ebp], eax
    mov    ecx, DWORD PTR $T4229[ebp+4]
    mov    DWORD PTR _bgp7$[ebp+4], ecx
    mov    edx, DWORD PTR $T4229[ebp+8]
    mov    DWORD PTR _bgp7$[ebp+8], edx

Below is given to a member function pointer values stored in the








Member function pointers stored value clearly, but these values again have what meaning? Here we come to a virtual function is called through the bgp1~bgp7 member function pointer assembly code analysis:

121  :     (bp->*bgp1)();

    mov    edx, DWORD PTR _bp$[ebp];The object first address to register EDX B
    mov    eax, DWORD PTR [edx+4];Edx+4 offset object B first address 4byte memory address, where the memory address (vbtable address) content to register eax
    mov    ecx, DWORD PTR _bgp1$[ebp+8];The offset object bgp1 first address 8byte memory contents to register ECX
    mov    edx, DWORD PTR [eax+ecx];Eax = vbtable first address ECX = 4 eax + ECX offset vbtable first address 4byte memory address
                                ;Here the offset vbtable first address 4byte memory contents (i.e. vbtable pointer offset of virtual base class subobject Top first address offset) to register EDX
    mov    eax, DWORD PTR _bp$[ebp];The object first address to register eax B
    lea    ecx, DWORD PTR [eax+edx+4];Eax = B EDX = vbtable is a pointer to the first address offset of virtual base class subobject Top first address offset of eax + EDX + 4 = B objects in a virtual base class subobject first address Top
    add    ecx, DWORD PTR _bgp1$[ebp+4];The offset bgp1 first address 4byte memory contents (0) additive content and ECX, get the object in B Top the first address virtual base class subobject
                                    ;The result stored in the register ECX, will serve as the implicit parameter passed to the corresponding Vcall function
    call    DWORD PTR _bgp1$[ebp];Bgp1 first address memory has the Vcall function corresponding address, call the corresponding Vcall function
                                 ;From this section of assembly code can be found in the third bgp1 storage is offset offset vbtable address of the first, and the second is
                                 ;Member function in the class to offset B objects in a virtual base class subobject the address of the first Top

; 122  :     (bp->*bgp2)();
       ;With the call to bgp1

    mov    ecx, DWORD PTR _bp$[ebp]
    mov    edx, DWORD PTR [ecx+4]
    mov    eax, DWORD PTR _bgp2$[ebp+8]
    mov    ecx, DWORD PTR [edx+eax]
    mov    edx, DWORD PTR _bp$[ebp]
    lea    ecx, DWORD PTR [edx+ecx+4]
    add    ecx, DWORD PTR _bgp2$[ebp+4]
    call    DWORD PTR _bgp2$[ebp]

; 123  :     (bp->*bgp3)();

    mov    eax, DWORD PTR _bp$[ebp];The object B to the eax first address register
    mov    ecx, DWORD PTR [eax+4];Eax = B eax + 4 = first address offset object B first address 4byte memory address
                              ;This will offset the object B object first address memory address 4byte content (i.e. vbtable first address) to register ECX
    mov    edx, DWORD PTR _bgp3$[ebp+8];The offset object bgp3 first address 8byte memory contents (0) to register EDX
    mov    eax, DWORD PTR [ecx+edx];ECX = vbtable first address EDX = 0 ECX + EDX = vbtable first address
                                ;Here the vbtable first address of the memory contents (i.e. vbtable pointer offset object B first address offset, -4) to register eax
    mov    ecx, DWORD PTR _bp$[ebp];The object first address to register ECX B
    lea    ecx, DWORD PTR [ecx+eax+4];ECX = B eax = -4 first address ECX + eax + 4 = ECX (object B first address)
                                   ;The object B first address to register ECX
    add    ecx, DWORD PTR _bgp3$[ebp+4];The offset object bgp3 first address 4byte memory contents (0) and ECX is obtained by adding the object B first address results stored in the ECX register
                                    ;The value of ECX will be used as the implicit parameter passed to the Vcall function corresponding
    call    DWORD PTR _bgp3$[ebp];Bgp3 first address memory address here have corresponding Vcall function, call the Vcall function
                                 ;Through the analysis, the bgp3 third preserved remains offset offset vbtable first address
                                 ;Offset second is a member function class offset object first address B, and bgp1

; 124  :     (bp->*bgp4)();
    ;With bgp3 calling
    mov    edx, DWORD PTR _bp$[ebp]
    mov    eax, DWORD PTR [edx+4]
    mov    ecx, DWORD PTR _bgp4$[ebp+8]
    mov    edx, DWORD PTR [eax+ecx]
    mov    eax, DWORD PTR _bp$[ebp]
    lea    ecx, DWORD PTR [eax+edx+4]
    add    ecx, DWORD PTR _bgp4$[ebp+4]
    call    DWORD PTR _bgp4$[ebp]

; 125  :     (bp->*bgp5)();
    ;With bgp3 calling
    mov    ecx, DWORD PTR _bp$[ebp]
    mov    edx, DWORD PTR [ecx+4]
    mov    eax, DWORD PTR _bgp5$[ebp+8]
    mov    ecx, DWORD PTR [edx+eax]
    mov    edx, DWORD PTR _bp$[ebp]
    lea    ecx, DWORD PTR [edx+ecx+4]
    add    ecx, DWORD PTR _bgp5$[ebp+4]
    call    DWORD PTR _bgp5$[ebp]

; 126  :     (bp->*bgp6)();
    ;With bgp3 calling
    mov    eax, DWORD PTR _bp$[ebp]
    mov    ecx, DWORD PTR [eax+4]
    mov    edx, DWORD PTR _bgp6$[ebp+8]
    mov    eax, DWORD PTR [ecx+edx]
    mov    ecx, DWORD PTR _bp$[ebp]
    lea    ecx, DWORD PTR [ecx+eax+4]
    add    ecx, DWORD PTR _bgp6$[ebp+4]
    call    DWORD PTR _bgp6$[ebp]

; 127  :     (bp->*bgp7)();
     ;With bgp3 calling
    mov    edx, DWORD PTR _bp$[ebp]
    mov    eax, DWORD PTR [edx+4]
    mov    ecx, DWORD PTR _bgp7$[ebp+8]
    mov    edx, DWORD PTR [eax+ecx]
    mov    eax, DWORD PTR _bp$[ebp]
    lea    ecx, DWORD PTR [eax+edx+4]
    add    ecx, DWORD PTR _bgp7$[ebp+4]
    call    DWORD PTR _bgp7$[ebp]

Through the above assembly code can be found, including virtual inherited member function pointer first store is still the corresponding Vcall address of the function, second items of preservation is a member function of class B address offset with respect to the first object (pointer pointing to the virtual base class member function is different, such as bgp1 and bgp2, they preservation is a member function of class offset virtual base class Top address of the first), compared with third of preservation is offset with respect to the first vbtable address.

Can see, compared with ordinary multiple inheritance, a member function pointer contains virtual inheritance also retain the information about vbtable, this is because, due to the particularity of the virtual base (its position after each time, derived subclasses are not the same, and non virtual base class has a fixed offset in the subclass in the virtual base), to locate the first address, must pass vbtable.

The c++ member function pointer from the assembly (a) and c++ member function pointer from the assembly (two) as discussed, include virtual inheritance, also can be the base class member function pointer is bound to a derived object or a derived class object pointer, such as (bp-> *lgp1) (), the compiler internal conversion (about this pointing from points to a derived object to point to the first address at the base class subobject first address the derived class), but not to the derived class member function pointer is bound to a base object or a base object pointer.

The c++ member function pointer from the assembly (a) and c++ member function pointer from the assembly (two) as discussed, include virtual inheritance, can also convert the base class member pointer to a derived class member function pointer, such as bgp1 = lgp1, but cannot speak the derived class member function pointer conversion the base class member function pointer.




Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Zachary at November 20, 2013 - 6:53 AM