今回は、try catchのアセンブラを確認します。
ただのjmp命令になるのではないかと予想してます。
takk@deb9:~/tmp$ cat -n t.cpp
1 int main()
2 {
3 int a;
4 a = 100;
5 try{
6 throw 10;
7 } catch (int e){
8 a = e;
9 }
10 return a;
11 }
takk@deb9:~/tmp$
上のプログラムをビルド、実行すると、catchでaの値が変化するので戻り値が10になりますね。
takk@deb9:~/tmp$ g++ t.cpp takk@deb9:~/tmp$ ./a.out;echo $? 10 takk@deb9:~/tmp$
では、アセンブラを見てみましょう。
takk@deb9:~/tmp$ g++ -S t.cpp
takk@deb9:~/tmp$ cat -n t.s
1 .file "t.cpp"
2 .text
3 .globl main
4 .type main, @function
5 main:
6 .LFB0:
7 .cfi_startproc
8 .cfi_personality 0x9b,DW.ref.__gxx_personality_v0
9 .cfi_lsda 0x1b,.LLSDA0
10 pushq %rbp
11 .cfi_def_cfa_offset 16
12 .cfi_offset 6, -16
13 movq %rsp, %rbp
14 .cfi_def_cfa_register 6
15 subq $16, %rsp
16 movl $100, -4(%rbp)
17 movl $4, %edi
18 call __cxa_allocate_exception@PLT
19 movl $10, (%rax)
20 movl $0, %edx
21 leaq _ZTIi(%rip), %rsi
22 movq %rax, %rdi
23 .LEHB0:
24 call __cxa_throw@PLT
25 .LEHE0:
26 .L6:
27 cmpq $1, %rdx
28 je .L5
29 movq %rax, %rdi
30 .LEHB1:
31 call _Unwind_Resume@PLT
32 .LEHE1:
33 .L5:
34 movq %rax, %rdi
35 call __cxa_begin_catch@PLT
36 movl (%rax), %eax
37 movl %eax, -8(%rbp)
38 movl -8(%rbp), %eax
39 movl %eax, -4(%rbp)
40 call __cxa_end_catch@PLT
41 movl -4(%rbp), %eax
42 leave
43 .cfi_def_cfa 7, 8
44 ret
45 .cfi_endproc
46 .LFE0:
47 .globl __gxx_personality_v0
48 .section .gcc_except_table,"a",@progbits
49 .align 4
50 .LLSDA0:
51 .byte 0xff
52 .byte 0x9b
53 .uleb128 .LLSDATT0-.LLSDATTD0
54 .LLSDATTD0:
55 .byte 0x1
56 .uleb128 .LLSDACSE0-.LLSDACSB0
57 .LLSDACSB0:
58 .uleb128 .LEHB0-.LFB0
59 .uleb128 .LEHE0-.LEHB0
60 .uleb128 .L6-.LFB0
61 .uleb128 0x1
62 .uleb128 .LEHB1-.LFB0
63 .uleb128 .LEHE1-.LEHB1
64 .uleb128 0
65 .uleb128 0
66 .LLSDACSE0:
67 .byte 0x1
68 .byte 0
69 .align 4
70 .long DW.ref._ZTIi-.
71 .LLSDATT0:
72 .text
73 .size main, .-main
74 .hidden DW.ref._ZTIi
75 .weak DW.ref._ZTIi
76 .section .data.DW.ref._ZTIi,"awG",@progbits,DW.ref._ZTIi,comdat
77 .align 8
78 .type DW.ref._ZTIi, @object
79 .size DW.ref._ZTIi, 8
80 DW.ref._ZTIi:
81 .quad _ZTIi
82 .hidden DW.ref.__gxx_personality_v0
83 .weak DW.ref.__gxx_personality_v0
84 .section .data.DW.ref.__gxx_personality_v0,"awG",@progbits,DW.ref.__gxx_personality_v0,comdat
85 .align 8
86 .type DW.ref.__gxx_personality_v0, @object
87 .size DW.ref.__gxx_personality_v0, 8
88 DW.ref.__gxx_personality_v0:
89 .quad __gxx_personality_v0
90 .ident "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
91 .section .note.GNU-stack,"",@progbits
takk@deb9:~/tmp$
何だこれはっ。全然単純じゃありません。throwでcatchへジャンプするだけだろうと思ってましたが、もっと複雑ですね。
throwしている箇所のアセンブラを見ると、callが使用されています。
24 call __cxa_throw@PLT
まるで関数のような呼び出しをしています。ステートメントなので、単純なロジックのアセンブラに置き換わるのだろうと思ってたら、サブルーチンなんですね。同じくcatchブロックもcallが使用されています。しかもブロックをbegin、endのサブルーチン呼び出しで囲ってます。またまた知らないことの発見で、脳に皺が増えました。



コメント