码迷,mamicode.com
首页 > 编程语言 > 详细

C++虚函数汇编

时间:2016-08-24 11:13:41      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:

参考这篇文章:http://blog.csdn.net/linyt/article/details/6336762

class Base      
{     
 public:     
    virtual void f() { }     
    virtual void g() { }     
};     
class Derive : public Base     
{     
  public:  
    virtual void f() {}  
};     
int main()     
{     
  Derive d; 
  int a = 4;
  Base *pb; 
  int b = 5;
  pb = &d;   
  int c = 6;
  pb->f();  
  return 0;  
}   

 

%esp
|
...
|
12
|
|  ------>Derive d
|
16
|
|  ------>int c
|
20
|
|  ------>Base *pb
|
24
|
|  ------>int b
|
28
|
|  ------>int a
|
32

 

    .file    "main.cpp"
    .section    .text$_ZN4Base1fEv,"x"
    .linkonce discard
    .align 2
    .globl    __ZN4Base1fEv
    .def    __ZN4Base1fEv;    .scl    2;    .type    32;    .endef
__ZN4Base1fEv:
LFB0:
    .cfi_startproc
    pushl    %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $4, %esp
    movl    %ecx, -4(%ebp)
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE0:
    .section    .text$_ZN4Base1gEv,"x"
    .linkonce discard
    .align 2
    .globl    __ZN4Base1gEv
    .def    __ZN4Base1gEv;    .scl    2;    .type    32;    .endef
__ZN4Base1gEv:
LFB1:
    .cfi_startproc
    pushl    %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $4, %esp
    movl    %ecx, -4(%ebp)
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE1:
    .section    .text$_ZN6Derive1fEv,"x"
    .linkonce discard
    .align 2
    .globl    __ZN6Derive1fEv
    .def    __ZN6Derive1fEv;    .scl    2;    .type    32;    .endef
__ZN6Derive1fEv:
LFB2:
    .cfi_startproc
    pushl    %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $4, %esp
    movl    %ecx, -4(%ebp)
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE2:
    .section    .text$_ZN4BaseC2Ev,"x"
    .linkonce discard
    .align 2
    .globl    __ZN4BaseC2Ev
    .def    __ZN4BaseC2Ev;    .scl    2;    .type    32;    .endef
__ZN4BaseC2Ev:                           //105行过来的
LFB6:
    .cfi_startproc
    pushl    %ebp                 
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $4, %esp                 //在栈上分配4个字节的空间
    movl    %ecx, -4(%ebp)           //将d的地址拷贝到上一步分配的4字节空间中
    movl    -4(%ebp), %eax           //将这个值拷贝到%eax
    movl    $__ZTV4Base+8, (%eax)    //将Base的vTable开始地址拷贝到%eax所指的栈上,也就是d的空间
    leave                            //返回,怎么没有恢复%ebp和%esp啊
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE6:
    .section    .text$_ZN6DeriveC1Ev,"x"
    .linkonce discard
    .align 2
    .globl    __ZN6DeriveC1Ev
    .def    __ZN6DeriveC1Ev;    .scl    2;    .type    32;    .endef
__ZN6DeriveC1Ev:                            //131行过来的
LFB9:
    .cfi_startproc
    pushl    %ebp                       //将%ebp保存到栈顶
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp                 //保存%esp
    .cfi_def_cfa_register 5
    subl    $4, %esp                   //在栈上分配4个字节的空间
    movl    %ecx, -4(%ebp)             //将d的地址拷贝到上一步分配的4字节空间中,使用movl %ecx, %esp应该也可以吧
    movl    -4(%ebp), %eax             //将这个值拷贝到%eax
    movl    %eax, %ecx                 //再将这个值拷贝到%ecx,为毛拷过来拷过去的
    call    __ZN4BaseC2Ev              //初始化base,见70行
    movl    -4(%ebp), %eax             //将d的地址拷贝到%eax
    movl    $__ZTV6Derive+8, (%eax)    //将Derive的vTable开始地址拷贝到d的空间,这会覆盖上一步Base所做的拷贝工作
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE9:
    .def    ___main;    .scl    2;    .type    32;    .endef
    .text
    .globl    _main
    .def    _main;    .scl    2;    .type    32;    .endef
_main:
LFB3:
    .cfi_startproc
    pushl    %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp         //保存栈帧,main返回时有用
    .cfi_def_cfa_register 5
    andl    $-16, %esp         //将%esp后四位清零,往栈增长方向移动,为了内存对齐
    subl    $32, %esp          //分配了32字节的空间
    call    ___main            //调用main函数啦
    leal    12(%esp), %eax     //将Derive d的地址拷贝到%eax
    movl    %eax, %ecx         //将%eax拷贝到%ecx,记着此时%ecx存储的是d的地址
    call    __ZN6DeriveC1Ev    //初始化d,第93行
    movl    $4, 28(%esp)       //int a = 4
    movl    $5, 24(%esp)       //int b = 5
    leal    12(%esp), %eax     //将d的地址拷贝到%eax
    movl    %eax, 20(%esp)     //*pb = &d
    movl    $6, 16(%esp)       //int c = 6
    movl    20(%esp), %eax     //将pb的值也就是d的地址拷贝到%eax
    movl    (%eax), %eax       //将d的值,也就是vTable拷贝到%eax
    movl    (%eax), %eax       //取vTable(Derive的)第一个字节的值,也就是方法f的地址,拷贝到%eax
    movl    20(%esp), %edx     //将pb的值也就是d的地址拷贝到%edx
    movl    %edx, %ecx         //ecx此时存储的是d的地址
    call    *%eax              //调用Derive的f函数
    movl    $0, %eax           
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE3:
    .globl    __ZTV6Derive
    .section    .rdata$_ZTV6Derive,"dr"
    .linkonce same_size
    .align 8
__ZTV6Derive:
    .long    0           
    .long    __ZTI6Derive
    .long    __ZN6Derive1fEv   //+8这里指向子类的方法
    .long    __ZN4Base1gEv     //仍然指向父类的方法
    .globl    __ZTV4Base
    .section    .rdata$_ZTV4Base,"dr"
    .linkonce same_size
    .align 8
__ZTV4Base:
    .long    0                 //+0
    .long    __ZTI4Base        //+4
    .long    __ZN4Base1fEv     //+8 这是Base的vTable开始的地址
    .long    __ZN4Base1gEv
    .globl    __ZTS6Derive
    .section    .rdata$_ZTS6Derive,"dr"
    .linkonce same_size
__ZTS6Derive:
    .ascii "6Derive\0"
    .globl    __ZTI6Derive
    .section    .rdata$_ZTI6Derive,"dr"
    .linkonce same_size
    .align 4
__ZTI6Derive:
    .long    __ZTVN10__cxxabiv120__si_class_type_infoE+8
    .long    __ZTS6Derive
    .long    __ZTI4Base
    .globl    __ZTS4Base
    .section    .rdata$_ZTS4Base,"dr"
    .linkonce same_size
__ZTS4Base:
    .ascii "4Base\0"
    .globl    __ZTI4Base
    .section    .rdata$_ZTI4Base,"dr"
    .linkonce same_size
    .align 4
__ZTI4Base:
    .long    __ZTVN10__cxxabiv117__class_type_infoE+8
    .long    __ZTS4Base
    .ident    "GCC: (GNU) 4.9.3"

 

C++虚函数汇编

标签:

原文地址:http://www.cnblogs.com/withparadox2/p/5802043.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!