标签:
参考这篇文章: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"
标签:
原文地址:http://www.cnblogs.com/withparadox2/p/5802043.html