反汇编 之 virtual-05 单类继承不重写虚函数

65 篇文章 1 订阅

#include <iostream>
#include <stdio.h>

class Base
{
    public:
        virtual void function_1()
        {
            printf("Base function_1...\n");
        }

        virtual void function_2()
        {
            printf("Base function_2...\n");
        }
    
        virtual void function_3()
        {
            printf("Base function_3...\n");
        }
};

class Sub : public Base
{
    public:
        virtual void function_4()
        {
            printf("Sub function_4...\n");
        }

        virtual void function_5()
        {
            printf("Sub function_5...\n");
        }
    
        virtual void function_6()
        {
            printf("Sub function_6...\n");
        }
};

int main(int argc, char ** argv)
{
    Sub sub;

    printf("sizeof = %ld\n",  sizeof(class Base));        /* 4 */
    printf("sizeof = %ld\n",  sizeof(class Sub));        /* 4 */

    printf("sub address is %x.\n", &sub);        // this 指针,是堆栈里面的地址。虚表的地址不是this指针,是this指针的前四个字节。
    printf("sub virtual table address is:%x\n", *(int*)&sub);       // 虚表地址。取this指针的前4个字节。*(char*)&base为取一个字节。    

    typedef void(*pfunction)(void);
    
    pfunction pf;

    int temp = *((int*)(*(int*)&sub) + 0);        // 取地址表里面的第一个值
                            // *(int*)&sub) 是虚表地址
                            // (int*) 转换成一个int*类型。
                            // *((int*)(*(int*)&sub) + 0), 加的是0,即取第一个4字节值。
    pf = (pfunction)*((int*)(*(int*)&sub) + 0);    // 或这样,取地址表里面的第一个值
    pf();                        // function_1

    pf = (pfunction)*((int*)(*(int*)&sub) + 1);    // 取第二个4字节值
    pf();                        // function_2

    for (int i = 0; i < 6; i++) {
        pf = (pfunction)*((int*)(*(int*)&sub) + i);
        pf();
    }
}

#if 0

1.因为没有重写关系。

sub对象

    ---------------        -------------
    | 0x123245    |    --->       | 0x123456  |    Base:function_1
    ---------------        -------------
    | ....        |        | 0x123457  |    Base:function_2
    ---------------        -------------
    | ....          |        | 0x123458  |    Base:function_3
    ---------------        -------------
    | ....        |        | 0x123457  |    Sub:function_4
    ---------------        -------------
    | ....          |        | 0x123457  |    Sub:function_5
    ---------------        -------------
    | 其它成员     |        | 0x123457  |    Sub:function_6
    ---------------        -------------
    | ....          |        | 0x000000  |
    ---------------        -------------

int main(int argc, char ** argv)
{
 80486b0:    55                       push   %ebp
 80486b1:    89 e5                    mov    %esp,%ebp
 80486b3:    83 e4 f0                 and    $0xfffffff0,%esp
 80486b6:    83 ec 20                 sub    $0x20,%esp
    Sub sub;
 80486b9:    8d 44 24 10              lea    0x10(%esp),%eax
 80486bd:    89 04 24                 mov    %eax,(%esp)
 80486c0:    e8 a3 01 00 00           call   8048868 <_ZN3SubC1Ev>

    printf("sizeof = %ld\n",  sizeof(class Base));        /* 4 */
 80486c5:    c7 44 24 04 04 00 00     movl   $0x4,0x4(%esp)
 80486cc:    00
 80486cd:    c7 04 24 9b 89 04 08     movl   $0x804899b,(%esp)
 80486d4:    e8 a7 fe ff ff           call   8048580 <printf@plt>
    printf("sizeof = %ld\n",  sizeof(class Sub));        /* 4 */
 80486d9:    c7 44 24 04 04 00 00     movl   $0x4,0x4(%esp)
 80486e0:    00
 80486e1:    c7 04 24 9b 89 04 08     movl   $0x804899b,(%esp)
 80486e8:    e8 93 fe ff ff           call   8048580 <printf@plt>

    printf("sub address is %x.\n", &sub);        // this 指针,是堆栈里面的地址。虚表的地址不是this指针,是this指针的前四个字节。
 80486ed:    8d 44 24 10              lea    0x10(%esp),%eax
 80486f1:    89 44 24 04              mov    %eax,0x4(%esp)
 80486f5:    c7 04 24 a9 89 04 08     movl   $0x80489a9,(%esp)
 80486fc:    e8 7f fe ff ff           call   8048580 <printf@plt>
    printf("sub virtual table address is:%x\n", *(int*)&sub);       // 虚表地址。取this指针的前4个字节。*(char*)&base为取一个字节。    
 8048701:    8d 44 24 10              lea    0x10(%esp),%eax
 8048705:    8b 00                    mov    (%eax),%eax
 8048707:    89 44 24 04              mov    %eax,0x4(%esp)
 804870b:    c7 04 24 c0 89 04 08     movl   $0x80489c0,(%esp)
 8048712:    e8 69 fe ff ff           call   8048580 <printf@plt>

    typedef void(*pfunction)(void);
    
    pfunction pf;

    int temp = *((int*)(*(int*)&sub) + 0);        // 取地址表里面的第一个值
 8048717:    8d 44 24 10              lea    0x10(%esp),%eax
 804871b:    8b 00                    mov    (%eax),%eax
 804871d:    8b 00                    mov    (%eax),%eax
 804871f:    89 44 24 18              mov    %eax,0x18(%esp)
                            // *(int*)&sub) 是虚表地址
                            // (int*) 转换成一个int*类型。
                            // *((int*)(*(int*)&sub) + 0), 加的是0,即取第一个4字节值。
    pf = (pfunction)*((int*)(*(int*)&sub) + 0);    // 或这样,取地址表里面的第一个值
 8048723:    8d 44 24 10              lea    0x10(%esp),%eax
 8048727:    8b 00                    mov    (%eax),%eax
 8048729:    8b 00                    mov    (%eax),%eax
 804872b:    89 44 24 14              mov    %eax,0x14(%esp)
    pf();                        // function_1
 804872f:    8b 44 24 14              mov    0x14(%esp),%eax
 8048733:    ff d0                    call   *%eax

    pf = (pfunction)*((int*)(*(int*)&sub) + 1);    // 取第二个4字节值
 8048735:    8d 44 24 10              lea    0x10(%esp),%eax
 8048739:    8b 00                    mov    (%eax),%eax
 804873b:    83 c0 04                 add    $0x4,%eax
 804873e:    8b 00                    mov    (%eax),%eax
 8048740:    89 44 24 14              mov    %eax,0x14(%esp)
    pf();                        // function_2
 8048744:    8b 44 24 14              mov    0x14(%esp),%eax
 8048748:    ff d0                    call   *%eax

    for (int i = 0; i < 6; i++) {
 804874a:    c7 44 24 1c 00 00 00     movl   $0x0,0x1c(%esp)
 8048751:    00
 8048752:    eb 24                    jmp    8048778 <main+0xc8>
        pf = (pfunction)*((int*)(*(int*)&sub) + i);
 8048754:    8b 44 24 1c              mov    0x1c(%esp),%eax
 8048758:    8d 14 85 00 00 00 00     lea    0x0(,%eax,4),%edx
 804875f:    8d 44 24 10              lea    0x10(%esp),%eax
 8048763:    8b 00                    mov    (%eax),%eax
 8048765:    01 d0                    add    %edx,%eax
 8048767:    8b 00                    mov    (%eax),%eax
 8048769:    89 44 24 14              mov    %eax,0x14(%esp)
        pf();
 804876d:    8b 44 24 14              mov    0x14(%esp),%eax
 8048771:    ff d0                    call   *%eax
    pf();                        // function_1

    pf = (pfunction)*((int*)(*(int*)&sub) + 1);    // 取第二个4字节值
    pf();                        // function_2

    for (int i = 0; i < 6; i++) {
 8048773:    83 44 24 1c 01           addl   $0x1,0x1c(%esp)
 8048778:    83 7c 24 1c 05           cmpl   $0x5,0x1c(%esp)
 804877d:    7e d5                    jle    8048754 <main+0xa4>
        pf = (pfunction)*((int*)(*(int*)&sub) + i);
        pf();
    }
}
 804877f:    b8 00 00 00 00           mov    $0x0,%eax
 8048784:    c9                       leave  
 8048785:    c3                       ret    

#endif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值