C++でx64アセンブラを覚える(その2)

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

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA