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してるだけでしたね。


コメント