我想确保在生成 exe/库之前了解我的代码实际上被编译成什么。我有以下用 C++98 编写的程序。这源于这个网站http://www.phpcompiler.org/articles/virtualinheritance.html 。
#include <stdio.h>
class top
{
public:
int t;
};
class left : virtual public top
{
public:
int l;
};
class right : virtual public top
{
public:
int r;
};
class bottom : public left, public right
{
public:
int b;
};
int main()
{
bottom *b = new bottom();
b->l = 5;
left *l = b;
printf("%d\n", l->l);
}
用 编译的程序集输出g++ -S main.cpp
在下面附有关于我认为应该如何分解的评论(这是我需要接受一些教育的地方)以及一些明确标记的问题。回答下面代码中的问题是我正在寻找的。
.file "main.cpp"
.section .text._ZN3topC2Ev,"axG",@progbits,_ZN3topC5Ev,comdat
.align 2
.weak _ZN3topC2Ev
.type _ZN3topC2Ev, @function
_ZN3topC2Ev:
.LFB3:
.cfi_startproc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pushq %rbp ; LFB3 Associated with the address for the class top constructor
.cfi_def_cfa_offset 16 ;
.cfi_offset 6, -16 ; %rdi, -8(%rbp) pushes 8 bytes (64 bits for t).
movq %rsp, %rbp ; onto the stack
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp)
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE3:
.size _ZN3topC2Ev, .-_ZN3topC2Ev
.weak _ZN3topC1Ev
.set _ZN3topC1Ev,_ZN3topC2Ev
.section .text._ZN4leftC2Ev,"axG",@progbits,_ZN4leftC2Ev,comdat
.align 2
.weak _ZN4leftC2Ev
.type _ZN4leftC2Ev, @function
_ZN4leftC2Ev:
.LFB6:
.cfi_startproc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pushq %rbp ; LFB6 Associated with the adress for the class left constructor
.cfi_def_cfa_offset 16 ;
.cfi_offset 6, -16 ; %rdi, -8(%rbp) pushes 8 bytes (64 bits for l).
movq %rsp, %rbp ; onto the stack
.cfi_def_cfa_register 6 ;
movq %rdi, -8(%rbp) ; %rdi, -16(%rbp) pushes 8 more bytes (64 bits for t).
movq %rsi, -16(%rbp) ;
movq -16(%rbp), %rax ; What does the rest of this do?
movq (%rax), %rdx
movq -8(%rbp), %rax
movq %rdx, (%rax)
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE6:
.size _ZN4leftC2Ev, .-_ZN4leftC2Ev
.section .text._ZN5rightC2Ev,"axG",@progbits,_ZN5rightC2Ev,comdat
.align 2
.weak _ZN5rightC2Ev
.type _ZN5rightC2Ev, @function
_ZN5rightC2Ev:
.LFB9:
.cfi_startproc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pushq %rbp ; LFB9 Associated with the adress for the class left constructor
.cfi_def_cfa_offset 16 ;
.cfi_offset 6, -16 ; %rdi, -8(%rbp) pushes 8 bytes (64 bits for r).
movq %rsp, %rbp ; onto the stack
.cfi_def_cfa_register 6 ;
movq %rdi, -8(%rbp) ; %rdi, -16(%rbp) pushes 8 more bytes (64 bits for t).
movq %rsi, -16(%rbp) ;
movq -16(%rbp), %rax ; What does the rest of this do?
movq (%rax), %rdx
movq -8(%rbp), %rax
movq %rdx, (%rax)
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE9:
.size _ZN5rightC2Ev, .-_ZN5rightC2Ev
.section .text._ZN6bottomC1Ev,"axG",@progbits,_ZN6bottomC1Ev,comdat
.align 2
.weak _ZN6bottomC1Ev
.type _ZN6bottomC1Ev, @function
_ZN6bottomC1Ev:
.LFB12:
.cfi_startproc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pushq %rbp ; LFB12 Associated with the adress for the class left constructor
.cfi_def_cfa_offset 16 ;
.cfi_offset 6, -16 ; %rdi, -8(%rbp) pushes 8 bytes (64 bits for b).
movq %rsp, %rbp ; onto the stack
.cfi_def_cfa_register 6 ;
subq $16, %rsp ; Construct all the base objects placing t into b only once?
movq %rdi, -8(%rbp) ;
movq -8(%rbp), %rax
addq $32, %rax
movq %rax, %rdi
call _ZN3topC2Ev
movl $_ZTT6bottom+8, %edx
movq -8(%rbp), %rax
movq %rdx, %rsi
movq %rax, %rdi
call _ZN4leftC2Ev
movl $_ZTT6bottom+16, %eax
movq -8(%rbp), %rdx
addq $16, %rdx
movq %rax, %rsi
movq %rdx, %rdi
call _ZN5rightC2Ev
movl $_ZTV6bottom+24, %edx
movq -8(%rbp), %rax
movq %rdx, (%rax)
movl $_ZTV6bottom+48, %edx
movq -8(%rbp), %rax
movq %rdx, 16(%rax)
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE12:
.size _ZN6bottomC1Ev, .-_ZN6bottomC1Ev
.section .rodata
.LC0:
.string "%d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pushq %rbp ; Store off the base pointer
.cfi_def_cfa_offset 16 ; Debug code to trace where stack pointer is?
.cfi_offset 6, -16 ;
movq %rsp, %rbp ; Move where stack pointer is to base pointer
.cfi_def_cfa_register 6 ;
pushq %rbx ; Store off what might have been in rbx
subq $24, %rsp ; Push argc onto stack
.cfi_offset 3, -24 ;
movl $40, %edi ; Push argv onto stack
call _Znwm ; Call new
movq %rax, %rbx ; Create room for b %rax contains address of memory
movq $0, (%rbx) ; location where new returned?
movq $0, 8(%rbx) ;
movq $0, 16(%rbx) ;
movq $0, 24(%rbx) ;
movq $0, 32(%rbx) ;
movq %rbx, %rdi ; Move that data into dynamic memory?
call _ZN6bottomC1Ev ; Call the construtor of the object
movq %rbx, -32(%rbp) ;
movq -32(%rbp), %rax ; Can someone explain how this code relates to
movl $5, 8(%rax) ; the explaination at:
movq -32(%rbp), %rax ; http://www.phpcompiler.org/articles/virtualinheritance.html?
movq %rax, -24(%rbp)
movq -24(%rbp), %rax
movl 8(%rax), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
addq $24, %rsp
popq %rbx
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.weak _ZTV6bottom
.section .rodata._ZTV6bottom,"aG",@progbits,_ZTV6bottom,comdat
.align 32
.type _ZTV6bottom, @object
.size _ZTV6bottom, 48
_ZTV6bottom:
.quad 32
.quad 0
.quad _ZTI6bottom
.quad 16
.quad -16
.quad _ZTI6bottom
.weak _ZTT6bottom
.section .rodata._ZTT6bottom,"aG",@progbits,_ZTV6bottom,comdat
.align 32
.type _ZTT6bottom, @object
.size _ZTT6bottom, 32
_ZTT6bottom:
.quad _ZTV6bottom+24
.quad _ZTC6bottom0_4left+24
.quad _ZTC6bottom16_5right+24
.quad _ZTV6bottom+48
.weak _ZTC6bottom0_4left
.section .rodata._ZTC6bottom0_4left,"aG",@progbits,_ZTV6bottom,comdat
.align 16
.type _ZTC6bottom0_4left, @object
.size _ZTC6bottom0_4left, 24
_ZTC6bottom0_4left:
.quad 32
.quad 0
.quad _ZTI4left
.weak _ZTC6bottom16_5right
.section .rodata._ZTC6bottom16_5right,"aG",@progbits,_ZTV6bottom,comdat
.align 16
.type _ZTC6bottom16_5right, @object
.size _ZTC6bottom16_5right, 24
_ZTC6bottom16_5right:
.quad 16
.quad 0
.quad _ZTI5right
.weak _ZTS6bottom
.section .rodata._ZTS6bottom,"aG",@progbits,_ZTS6bottom,comdat
.type _ZTS6bottom, @object
.size _ZTS6bottom, 8
_ZTS6bottom:
.string "6bottom"
.weak _ZTI6bottom
.section .rodata._ZTI6bottom,"aG",@progbits,_ZTI6bottom,comdat
.align 32
.type _ZTI6bottom, @object
.size _ZTI6bottom, 56
_ZTI6bottom:
.quad _ZTVN10__cxxabiv121__vmi_class_type_infoE+16
.quad _ZTS6bottom
.long 2
.long 2
.quad _ZTI4left
.quad 2
.quad _ZTI5right
.quad 4098
.weak _ZTS5right
.section .rodata._ZTS5right,"aG",@progbits,_ZTS5right,comdat
.type _ZTS5right, @object
.size _ZTS5right, 7
_ZTS5right:
.string "5right"
.weak _ZTI5right
.section .rodata._ZTI5right,"aG",@progbits,_ZTI5right,comdat
.align 32
.type _ZTI5right, @object
.size _ZTI5right, 40
_ZTI5right:
.quad _ZTVN10__cxxabiv121__vmi_class_type_infoE+16
.quad _ZTS5right
.long 0
.long 1
.quad _ZTI3top
.quad -6141
.weak _ZTS4left
.section .rodata._ZTS4left,"aG",@progbits,_ZTS4left,comdat
.type _ZTS4left, @object
.size _ZTS4left, 6
_ZTS4left:
.string "4left"
.weak _ZTI4left
.section .rodata._ZTI4left,"aG",@progbits,_ZTI4left,comdat
.align 32
.type _ZTI4left, @object
.size _ZTI4left, 40
_ZTI4left:
.quad _ZTVN10__cxxabiv121__vmi_class_type_infoE+16
.quad _ZTS4left
.long 0
.long 1
.quad _ZTI3top
.quad -6141
.weak _ZTS3top
.section .rodata._ZTS3top,"aG",@progbits,_ZTS3top,comdat
.type _ZTS3top, @object
.size _ZTS3top, 5
_ZTS3top:
.string "3top"
.weak _ZTI3top
.section .rodata._ZTI3top,"aG",@progbits,_ZTI3top,comdat
.align 16
.type _ZTI3top, @object
.size _ZTI3top, 16
_ZTI3top:
.quad _ZTVN10__cxxabiv117__class_type_infoE+16
.quad _ZTS3top
.ident "GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3"
.section .note.GNU-stack,"",@progbits