C++のアセンブラも眺めたくなりました。
今回はこのサンプルのアセンブラを見てみます。
takk@deb9:~/tmp$ cat -n t.cpp 1 class Sample{ 2 int a; 3 public: 4 Sample(int a){ 5 this->a = a; 6 } 7 int Get_a(){ 8 return this->a; 9 } 10 }; 11 12 int main() 13 { 14 Sample *o = new Sample(100); 15 16 return o->Get_a(); 17 } takk@deb9:~/tmp$
実行すると、コマンドの戻り値に100を返してくれます。
takk@deb9:~/tmp$ g++ t.cpp takk@deb9:~/tmp$ ./a.out;echo $? 100 takk@deb9:~/tmp$
ではアセンブラコード全文です。
takk@deb9:~/tmp$ g++ -S t.cpp takk@deb9:~/tmp$ cat -n t.s 1 .file "t.cpp" 2 .section .text._ZN6SampleC2Ei,"axG",@progbits,_ZN6SampleC5Ei,comdat 3 .align 2 4 .weak _ZN6SampleC2Ei 5 .type _ZN6SampleC2Ei, @function 6 _ZN6SampleC2Ei: 7 .LFB1: 8 .cfi_startproc 9 pushq %rbp 10 .cfi_def_cfa_offset 16 11 .cfi_offset 6, -16 12 movq %rsp, %rbp 13 .cfi_def_cfa_register 6 14 movq %rdi, -8(%rbp) 15 movl %esi, -12(%rbp) 16 movq -8(%rbp), %rax 17 movl -12(%rbp), %edx 18 movl %edx, (%rax) 19 nop 20 popq %rbp 21 .cfi_def_cfa 7, 8 22 ret 23 .cfi_endproc 24 .LFE1: 25 .size _ZN6SampleC2Ei, .-_ZN6SampleC2Ei 26 .weak _ZN6SampleC1Ei 27 .set _ZN6SampleC1Ei,_ZN6SampleC2Ei 28 .section .text._ZN6Sample5Get_aEv,"axG",@progbits,_ZN6Sample5Get_aEv,comdat 29 .align 2 30 .weak _ZN6Sample5Get_aEv 31 .type _ZN6Sample5Get_aEv, @function 32 _ZN6Sample5Get_aEv: 33 .LFB3: 34 .cfi_startproc 35 pushq %rbp 36 .cfi_def_cfa_offset 16 37 .cfi_offset 6, -16 38 movq %rsp, %rbp 39 .cfi_def_cfa_register 6 40 movq %rdi, -8(%rbp) 41 movq -8(%rbp), %rax 42 movl (%rax), %eax 43 popq %rbp 44 .cfi_def_cfa 7, 8 45 ret 46 .cfi_endproc 47 .LFE3: 48 .size _ZN6Sample5Get_aEv, .-_ZN6Sample5Get_aEv 49 .text 50 .globl main 51 .type main, @function 52 main: 53 .LFB4: 54 .cfi_startproc 55 pushq %rbp 56 .cfi_def_cfa_offset 16 57 .cfi_offset 6, -16 58 movq %rsp, %rbp 59 .cfi_def_cfa_register 6 60 pushq %rbx 61 subq $24, %rsp 62 .cfi_offset 3, -24 63 movl $4, %edi 64 call _Znwm@PLT 65 movq %rax, %rbx 66 movl $100, %esi 67 movq %rbx, %rdi 68 call _ZN6SampleC1Ei 69 movq %rbx, -24(%rbp) 70 movq -24(%rbp), %rax 71 movq %rax, %rdi 72 call _ZN6Sample5Get_aEv 73 addq $24, %rsp 74 popq %rbx 75 popq %rbp 76 .cfi_def_cfa 7, 8 77 ret 78 .cfi_endproc 79 .LFE4: 80 .size main, .-main 81 .ident "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516" 82 .section .note.GNU-stack,"",@progbits takk@deb9:~/tmp$
C言語と比べてコードが長くなりました。
この行で、Sampleコンストラクタの呼び出しをして、
68 call _ZN6SampleC1Ei
この行で、Get_aメソッドの呼び出しをしてるだけですね。
72 call _ZN6Sample5Get_aEv
C言語の時と同じで、アセンブラでも関数をcallしてるだけってことが分かりました。
インスタンスを増やしても同じでしょうか。
別インスタンス作って実行してみます。
takk@deb9:~/tmp$ cat -n t.cpp 1 class Sample{ 2 int a; 3 public: 4 Sample(int a){ 5 this->a = a; 6 } 7 int Get_a(){ 8 return this->a; 9 } 10 }; 11 12 int main() 13 { 14 Sample *o1 = new Sample(100); 15 Sample *o2 = new Sample(150); 16 17 return o1->Get_a() + o2->Get_a(); 18 } takk@deb9:~/tmp$
生成アセンブラを比較。
takk@deb9:~/tmp$ mv t.s t1.s takk@deb9:~/tmp$ g++ -o t2.s -S t.cpp takk@deb9:~/tmp$ diff t1.s t2.s 69a70,76 > movl $4, %edi > call _Znwm@PLT > movq %rax, %rbx > movl $150, %esi > movq %rbx, %rdi > call _ZN6SampleC1Ei > movq %rbx, -32(%rbp) 72a80,84 > movl %eax, %ebx > movq -32(%rbp), %rax > movq %rax, %rdi > call _ZN6Sample5Get_aEv > addl %ebx, %eax takk@deb9:~/tmp$
インスタンスを増やしても、所詮は関数呼び出しなので、callしてるだけでしたね。
コメント