C++是一种面向对象的高级语言,但是由于其基于C语言发展而来,因此其内在原理和C语言如出一辙,于是就来看看C++程序翻译成汇编代码是啥样的(在x86 linux环境下,使用g++ 翻译得到的结果),采用了C++11新标准,因此可以顺路看一下C++11中的mov语义究竟是如何实现的
一、翻译的原cpp文件:
extern double sqrt(double x); extern double abs(double x); struct Position { public: Position(double px = 0 , double py = 0 , double pz = 0) : px(px) , py(py) , pz(pz){} double px , py , pz; }; int distance(const Position &x , const Position &y) { return abs(sqrt((x.px * x.px + x.py * x.py + x.pz * x.pz)) - sqrt((y.px * y.px + y.py * y.py + y.pz * y.pz))); } class Gun { public: Gun(unsigned nbullet = 0) : nbullet(nbullet){} virtual bool shot(const Position &pfrom , const Position &pto); void set_bullet(unsigned n) { nbullet = n; } unsigned get_bullet()const { return nbullet; } virtual Gun* copy_self()const; virtual ~Gun(){} private: unsigned nbullet; }; Gun* Gun::copy_self()const { return new Gun(*this); } bool Gun::shot(const Position &pfrom , const Position &pto) { if(nbullet == 0) return false; else nbullet--; return true; } class HandGun : public Gun { public: HandGun(unsigned nbullet = 0 , double dist = 0) : Gun(nbullet) , dist(dist){} bool shot(const Position &px , const Position &py); HandGun* copy_self()const; void set_dist(double d) { dist = d; } double get_dist()const { return dist; } private: double dist; }; HandGun* HandGun::copy_self()const { return new HandGun(*this); } bool HandGun::shot(const Position &px , const Position &py) { if(!Gun::shot(px , py)) return false; return distance(px , py) < dist; } class Soldior { public: Soldior(const Position &pos , const Gun *g = nullptr) : pos(pos) { if(g == nullptr) gun = nullptr; else gun = g->copy_self(); } Soldior(const Soldior& s) { if(s.gun == nullptr) gun = nullptr; else gun = s.gun->copy_self(); pos = s.pos; } Soldior(Soldior &&s) noexcept { gun = s.gun; s.gun = nullptr; pos = s.pos; } bool shot(const Position &pt) { return gun->shot(pos , pt); } Soldior& operator=(const Soldior &s) { if(this == &s) return *this; if(gun != nullptr) delete gun; if(s.gun == nullptr) gun = nullptr; else gun = s.gun->copy_self(); pos = s.pos; return *this; } Soldior& operator=(Soldior &&s) { if(this == &s) return *this; if(gun != nullptr) delete gun; gun = s.gun; s.gun = nullptr; pos = s.pos; return *this; } ~Soldior() { if(gun != nullptr) delete gun; } private: Gun *gun; Position pos; }; extern Soldior getSoldior(); int main(int argc , char *argv[]) { Gun *g = new Gun(100); Soldior *s = new Soldior(Position(20 , 30 , 50) , g); *s = getSoldior(); delete g; delete s; }
_ZN8PositionC2Eddd: ;constructor of Position pushq %rbp movq %rsp, %rbp ;save rbp movq %rdi, -8(%rbp) ;get this pointer movsd %xmm0, -16(%rbp) ;get px movsd %xmm1, -24(%rbp) ;get py movsd %xmm2, -32(%rbp) ;get pz movq -8(%rbp), %rdx movq -16(%rbp), %rax movq %rax, (%rdx) ;init px movq -8(%rbp), %rdx movq -24(%rbp), %rax movq %rax, 8(%rdx) ;init py movq -8(%rbp), %rdx movq -32(%rbp), %rax movq %rax, 16(%rdx) ;init pz popq %rbp ;recover rbp ret _Z8distanceRK8PositionS1_: ;distance pushq %rbp movq %rsp, %rbp subq $32, %rsp ;extend stack movq %rdi, -8(%rbp) ;get address of x movq %rsi, -16(%rbp) ;get address of y movq -8(%rbp), %rax movsd (%rax), %xmm1 ;get x.px movq -8(%rbp), %rax movsd (%rax), %xmm0 ;get x.px mulsd %xmm0, %xmm1 ;%xmm1 = x.px * x.px movq -8(%rbp), %rax movsd 8(%rax), %xmm2 movq -8(%rbp), %rax movsd 8(%rax), %xmm0 mulsd %xmm2, %xmm0 ;%xmm0 = x.py * x.py addsd %xmm0, %xmm1 ;%xmm1 += %xmm0 movq -8(%rbp), %rax movsd 16(%rax), %xmm2 movq -8(%rbp), %rax movsd 16(%rax), %xmm0 mulsd %xmm2, %xmm0 ;%xmm0 = x.pz * x.pz addsd %xmm1, %xmm0 ;%xmm0 += %xmm1 call _Z4sqrtd ;call sqrt with argument %xmm0 movsd %xmm0, -24(%rbp) ;save return value of sqrt movq -16(%rbp), %rax ;mov address value of y into %rax movsd (%rax), %xmm1 movq -16(%rbp), %rax movsd (%rax), %xmm0 mulsd %xmm0, %xmm1 ;%xmm1 = y.px * y.px movq -16(%rbp), %rax movsd 8(%rax), %xmm2 movq -16(%rbp), %rax movsd 8(%rax), %xmm0 mulsd %xmm2, %xmm0 ;%xmm0 = y.py * y.py addsd %xmm0, %xmm1 ;%xmm1 += %xmm0 movq -16(%rbp), %rax movsd 16(%rax), %xmm2 movq -16(%rbp), %rax movsd 16(%rax), %xmm0 mulsd %xmm2, %xmm0 ;%xmm0 = y.pz * y.pz addsd %xmm1, %xmm0 ;%xmm0 += %xmm1 call _Z4sqrtd ;call sqrt with argument %xmm0 movsd -24(%rbp), %xmm3 ;mov return value of first call to sqrt to %xmm3 subsd %xmm0, %xmm3 ;%xmm3 -= %xmm0 movapd %xmm3, %xmm0 ;save %xmm3 to %xmm0 for pass to call absd as argument call _Z3absd ;call absd cvttsd2si %xmm0, %eax ret _ZN3GunC2Ej: ;constructor of Gun pushq %rbp movq %rsp, %rbp movq %rdi, -8(%rbp) ;get this pointer movl %esi, -12(%rbp) ;get nbullet movq -8(%rbp), %rax movq $_ZTV3Gun+16, (%rax) ;pointer to virtual function table of class Gun movq -8(%rbp), %rax movl -12(%rbp), %edx movl %edx, 8(%rax) ;init nbullet popq %rbp ret _ZN3GunD2Ev: pushq %rbp movq %rsp, %rbp subq $16, %rsp ;extend stack storage movq %rdi, -8(%rbp) ;get this pointer movq -8(%rbp), %rax movq $_ZTV3Gun+16, (%rax) ;get pointer to virtual function table of class Gun movl $0, %eax testl %eax, %eax je .L5 movq -8(%rbp), %rax movq %rax, %rdi call _ZdlPv .L5: leave ret _ZN3GunC2ERKS_: ;copy constructor of Gun pushq %rbp movq %rsp, %rbp movq %rdi, -8(%rbp) ;get this pointer movq %rsi, -16(%rbp) ;get address of argument gun movq -8(%rbp), %rax movq $_ZTV3Gun+16, (%rax) ;set pointer to virtual table with class Gun's virtual table address movq -16(%rbp), %rax movl 8(%rax), %edx ;%edx point to address of argument gun's nbullet movq -8(%rbp), %rax movl %edx, 8(%rax) ;init this->nbullet popq %rbp ret _ZNK3Gun9copy_selfEv: ;Gun::copy_self pushq %rbp movq %rsp, %rbp pushq %rbx subq $24, %rsp ;extend stack movq %rdi, -24(%rbp) ;get this pointer movl $16, %edi ;mov size of Gun to %edi call _Znwm ;alloc memory on heap movq %rax, %rbx ;this pointer to new gun movq -24(%rbp), %rax movq %rax, %rsi ;my own this pointer movq %rbx, %rdi ;this pointer to new gun call _ZN3GunC1ERKS_ ;call copy constructor of Gun movq %rbx, %rax ;set return value as this pointer to new gun addq $24, %rsp ;resave stack popq %rbx popq %rbp ret _ZN3Gun4shotERK8PositionS2_: ;Gun::shot pushq %rbp movq %rsp, %rbp movq %rdi, -8(%rbp) ;this pointer movq %rsi, -16(%rbp) ;address of x movq %rdx, -24(%rbp) ;address of y movq -8(%rbp), %rax movl 8(%rax), %eax ;address of this->nbullet testl %eax, %eax jne .L14 ;nbullet != 0 movl $0, %eax jmp .L13 .L14: movq -8(%rbp), %rax movl 8(%rax), %eax ;address of this->nbullet leal -1(%rax), %edx movq -8(%rbp), %rax movl %edx, 8(%rax) .L13: popq %rbp ret _ZN7HandGunC2Ejd: ;constructor of HandGun pushq %rbp movq %rsp, %rbp subq $32, %rsp movq %rdi, -8(%rbp) movl %esi, -12(%rbp) movsd %xmm0, -24(%rbp) movq -8(%rbp), %rax movl -12(%rbp), %edx movl %edx, %esi ;set nbullet movq %rax, %rdi ;set this pointer call _ZN3GunC2Ej ;call constructor of Gun movq -8(%rbp), %rax movq $_ZTV7HandGun+16, (%rax) ;set virtual function pointer movq -8(%rbp), %rdx movq -24(%rbp), %rax movq %rax, 16(%rdx) ;init dist leave ret _ZN7HandGunC2ERKS_: ;copy constructor of HandGun pushq %rbp movq %rsp, %rbp subq $16, %rsp movq %rdi, -8(%rbp) movq %rsi, -16(%rbp) movq -16(%rbp), %rdx movq -8(%rbp), %rax movq %rdx, %rsi ;set arg gun's this pointer movq %rax, %rdi ;set my own this pointer call _ZN3GunC2ERKS_ ;call Gun's copy constructor movq -8(%rbp), %rax movq $_ZTV7HandGun+16, (%rax) ;set virtual function pointer movq -16(%rbp), %rax movq 16(%rax), %rax ;get arg gun's dist movq -8(%rbp), %rdx movq %rax, 16(%rdx) ;init dist leave ret _ZNK7HandGun9copy_selfEv: ;HandGun::copy_self pushq %rbp movq %rsp, %rbp pushq %rbx subq $24, %rsp movq %rdi, -24(%rbp) ;my own this pointer movl $24, %edi call _Znwm movq %rax, %rbx ;get address of new gun movq -24(%rbp), %rax movq %rax, %rsi ;set arg gun's address (my own this pointer) movq %rbx, %rdi ;set this pointer (new gun's this pointer) call _ZN7HandGunC1ERKS_ ;call copy constructor of HandGun movq %rbx, %rax ;set new this pointer as return value addq $24, %rsp ;resave stack popq %rbx popq %rbp ret _ZN7HandGun4shotERK8PositionS2_: ;HandGun::shot pushq %rbp movq %rsp, %rbp subq $32, %rsp movq %rdi, -8(%rbp) movq %rsi, -16(%rbp) movq %rdx, -24(%rbp) movq -8(%rbp), %rax ;this movq -24(%rbp), %rdx ;addr of x movq -16(%rbp), %rcx ;addr of y movq %rcx, %rsi ;set y movq %rax, %rdi ;set this call _ZN3Gun4shotERK8PositionS2_ ;call Gun::shot xorl $1, %eax ;check return value testb %al, %al je .L21 ;true movl $0, %eax jmp .L22 .L21: movq -24(%rbp), %rdx movq -16(%rbp), %rax movq %rdx, %rsi ;set x movq %rax, %rdi ;set y call _Z8distanceRK8PositionS1_ ;call distance cvtsi2sd %eax, %xmm0 movq -8(%rbp), %rax movsd 16(%rax), %xmm1 ucomisd %xmm0, %xmm1 seta %al .L22: leave ret _ZN7SoldiorC2ERK8PositionPK3Gun: ;constructor of Soldior pushq %rbp movq %rsp, %rbp subq $32, %rsp movq %rdi, -8(%rbp) movq %rsi, -16(%rbp) movq %rdx, -24(%rbp) movq -8(%rbp), %rax ;this movq -16(%rbp), %rdx ;addr of pos movq (%rdx), %rcx movq %rcx, 8(%rax) ;init pos.px movq 8(%rdx), %rcx movq %rcx, 16(%rax) ;init pos.py movq 16(%rdx), %rdx movq %rdx, 24(%rax) ;init pos.pz cmpq $0, -24(%rbp) jne .L24 ;g != nullptr movq -8(%rbp), %rax movq $0, (%rax) ;init gun as nullptr jmp .L23 .L24: movq -24(%rbp), %rax ;this movq (%rax), %rax ;pointer to Gun's virtual functions table addq $8, %rax movq (%rax), %rax ;second function pointer of g's virtual table movq -24(%rbp), %rdx movq %rdx, %rdi ;set g as 'this' argument call *%rax ;call g->copy_self movq -8(%rbp), %rdx movq %rax, (%rdx) ;gun = g .L23: leave ret _ZN7SoldioraSEOS_: ;mov assignment pushq %rbp movq %rsp, %rbp subq $16, %rsp movq %rdi, -8(%rbp) movq %rsi, -16(%rbp) movq -8(%rbp), %rax cmpq -16(%rbp), %rax jne .L27 ;if(this != &s) movq -8(%rbp), %rax jmp .L28 .L27: movq -8(%rbp), %rax movq (%rax), %rax testq %rax, %rax je .L29 ;this->gun == nullptr movq -8(%rbp), %rax movq (%rax), %rax testq %rax, %rax je .L29 movq -8(%rbp), %rax movq (%rax), %rax movq (%rax), %rax addq $24, %rax movq (%rax), %rax movq -8(%rbp), %rdx movq (%rdx), %rdx movq %rdx, %rdi call *%rax ;call gun's destructor .L29: movq -16(%rbp), %rax movq (%rax), %rdx movq -8(%rbp), %rax movq %rdx, (%rax) ;gun = s->gun movq -16(%rbp), %rax movq $0, (%rax) ;s->gun = nullptr movq -8(%rbp), %rax movq -16(%rbp), %rdx movq 8(%rdx), %rcx movq %rcx, 8(%rax) ;pos.px = s->pos.px movq 16(%rdx), %rcx movq %rcx, 16(%rax) ;pos.py = s->pos.py movq 24(%rdx), %rdx movq %rdx, 24(%rax) ;pos.pz = s->pos.pz movq -8(%rbp), %rax ;return this .L28: leave ret _ZN7SoldiorD2Ev: ;destructor of Soldior pushq %rbp movq %rsp, %rbp subq $16, %rsp movq %rdi, -8(%rbp) movq -8(%rbp), %rax movq (%rax), %rax ;%rax = gun testq %rax, %rax je .L30 ;gun == nullptr movq -8(%rbp), %rax movq (%rax), %rax testq %rax, %rax je .L30 ;gun == nullptr movq -8(%rbp), %rax movq (%rax), %rax movq (%rax), %rax ;gun->vptr addq $24, %rax ;third function pointer in gun's virtual table movq (%rax), %rax movq -8(%rbp), %rdx movq (%rdx), %rdx ;get gun movq %rdx, %rdi ;set gun as 'this' argument call *%rax ;call gun's destructor .L30: leave ret main: pushq %rbp movq %rsp, %rbp pushq %r12 pushq %rbx subq $80, %rsp movl %edi, -68(%rbp) movq %rsi, -80(%rbp) movl $16, %edi ;set alloc size as Gun call _Znwm ;alloc memory on heap movq %rax, %rbx ;%rbx is this pointer of new gun movl $100, %esi ;set nbullet movq %rbx, %rdi ;set 'this' arg call _ZN3GunC1Ej ;call constructor of Gun movq %rbx, -64(%rbp) ;save %rbx movabsq $4632233691727265792, %rcx ;constexpr accessed as static address movabsq $4629137466983448576, %rdx movabsq $4626322717216342016, %rax leaq -48(%rbp), %rsi movq %rcx, -88(%rbp) movsd -88(%rbp), %xmm2 ;px movq %rdx, -88(%rbp) movsd -88(%rbp), %xmm1 ;py movq %rax, -88(%rbp) movsd -88(%rbp), %xmm0 ;pz movq %rsi, %rdi ;set 'this' arg call _ZN8PositionC1Eddd ;call constructor of Position leaq -48(%rbp), %r12 movl $32, %edi ;set alloc size as Soldior's size call _Znwm movq %rax, %rbx ;s movq -64(%rbp), %rax movq %rax, %rdx ;set g movq %r12, %rsi ;set pos movq %rbx, %rdi ;set 'this' arg call _ZN7SoldiorC1ERK8PositionPK3Gun ;call Soldior's constructor movq %rbx, -56(%rbp) ;save %rbx leaq -48(%rbp), %rax movq %rax, %rdi ;set return addr of next function call _Z10getSoldiorv ;call getSoldior leaq -48(%rbp), %rdx ;get return val movq -56(%rbp), %rax ;get s movq %rdx, %rsi ;set 's' arg movq %rax, %rdi ;set 'this' arg call _ZN7SoldioraSEOS_ ;call mov assignment of Soldior leaq -48(%rbp), %rax movq %rax, %rdi call _ZN7SoldiorD1Ev ;delete return val of getSoldior movl $0, %eax jmp .L38 .L37: movq %rax, %r12 movq %rbx, %rdi call _ZdlPv movq %r12, %rax movq %rax, %rdi call _Unwind_Resume .L38: addq $80, %rsp popq %rbx popq %r12 popq %rbp ret _ZTV3Gun: ;Gun's virtual functions table .quad 0 .quad _ZTI3Gun ;some information of this table , we can ignore .quad _ZN3Gun4shotERK8PositionS2_ .quad _ZNK3Gun9copy_selfEv .quad _ZN3GunD1Ev .quad _ZN3GunD0Ev .weak _ZTI7HandGun .section .rodata._ZTI7HandGun,"aG",@progbits,_ZTI7HandGun,comdat .align 16 .type _ZTI7HandGun, @object .size _ZTI7HandGun, 24 _ZTV7HandGun: ;virtual function table of HandGun .quad 0 .quad _ZTI7HandGun .quad _ZN7HandGun4shotERK8PositionS2_ .quad _ZNK7HandGun9copy_selfEv .quad _ZN7HandGunD1Ev .quad _ZN7HandGunD0Ev .section .text._ZN7HandGunD2Ev,"axG",@progbits,_ZN7HandGunD5Ev,comdat .align 2 .weak _ZN7HandGunD2Ev .type _ZN7HandGunD2Ev, @function _ZN7HandGunD2Ev: ;destructor of HandGun pushq %rbp movq %rsp, %rbp subq $16, %rsp movq %rdi, -8(%rbp) movq -8(%rbp), %rax movq $_ZTV7HandGun+16, (%rax) ;set vptr movq -8(%rbp), %rax movq %rax, %rdi call _ZN3GunD2Ev ;call Gun's destructor movl $0, %eax testl %eax, %eax je .L39 movq -8(%rbp), %rax movq %rax, %rdi call _ZdlPv .L39: leave ret
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/yuanliang01xiaolang/article/details/46754809