今回は、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のサブルーチン呼び出しで囲ってます。またまた知らないことの発見で、脳に皺が増えました。
コメント