gcc最適化オプションとアセンブラ


アニメ「ゾンビランドサガ」

ゾンビは首取れても平気です。イリュージョンです。面白いしゾンビだけど後味もいいです。

タイトルが変わりましたが、やってることは同じで、
C言語のソースコードが、どのようなアセンブラコードになるかの確認です。

ではいつものこのソースです。

takk@deb9:~/tmp$ cat -n t.c
     1  int main()
     2  {
     3          int a=10;
     4          int b;
     5          if(a == 10)
     6                  b = 100;
     7          else
     8                  b = 200;
     9  }
takk@deb9:~/tmp$

これを、-Oオプションをつけてgccにかけてみます。

takk@deb9:~/tmp$ gcc -O -S t.c
takk@deb9:~/tmp$ cat -n t.s
     1          .file   "t.c"
     2          .text
     3          .globl  main
     4          .type   main, @function
     5  main:
     6  .LFB0:
     7          .cfi_startproc
     8          movl    $0, %eax
     9          ret
    10          .cfi_endproc
    11  .LFE0:
    12          .size   main, .-main
    13          .ident  "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
    14          .section        .note.GNU-stack,"",@progbits
takk@deb9:~/tmp$

なんてことでしょう。
アセンブラのコードのどこにも、ジャンプ命令がありません。eaxに0を格納しているだけのソースです。

変数aに、何が入っているかの判定もしないし、変数bに、100または、200を代入したりしません。何もせず、終了するアセンブラコードとなっています。これが最適化ですね。
つまり、変数aも変数bも外部のどこにも影響しないので、何もしないのと同じなのです。

あれ?

となると、デバッグする時は、どうなるのでしょうか。ステップ実行しても、どこにも止まらないのではないでしょうか。
GDB使うときは、-gオプションをつけますので、-gオプションもつけたアセンブラコードをみてみましょう。

takk@deb9:~/tmp$ gcc -O -g -S t.c
takk@deb9:~/tmp$ cat -n t.s
     1          .file   "t.c"
     2          .text
     3  .Ltext0:
     4          .globl  main
     5          .type   main, @function
     6  main:
     7  .LFB0:
     8          .file 1 "t.c"
     9          .loc 1 2 0
    10          .cfi_startproc
    11  .LVL0:
    12          .loc 1 9 0
    13          movl    $0, %eax
    14          ret
    15          .cfi_endproc
    16  .LFE0:
    17          .size   main, .-main
    18  .Letext0:
    19          .section        .debug_info,"",@progbits
    20  .Ldebug_info0:
    21          .long   0x67
    22          .value  0x4
    23          .long   .Ldebug_abbrev0
    24          .byte   0x8
    25          .uleb128 0x1
    26          .long   .LASF0
    27          .byte   0xc
    28          .string "t.c"
    29          .long   .LASF1
    30          .quad   .Ltext0
    31          .quad   .Letext0-.Ltext0
    32          .long   .Ldebug_line0
    33          .uleb128 0x2
    34          .long   .LASF2
    35          .byte   0x1
    36          .byte   0x1
    37          .long   0x63
    38          .quad   .LFB0
    39          .quad   .LFE0-.LFB0
    40          .uleb128 0x1
    41          .byte   0x9c
    42          .long   0x63
    43          .uleb128 0x3
    44          .string "a"
    45          .byte   0x1
    46          .byte   0x3
    47          .long   0x63
    48          .byte   0xa
    49          .uleb128 0x3
    50          .string "b"
    51          .byte   0x1
    52          .byte   0x4
    53          .long   0x63
    54          .byte   0x64
    55          .byte   0
    56          .uleb128 0x4
    57          .byte   0x4
    58          .byte   0x5
    59          .string "int"
    60          .byte   0
    61          .section        .debug_abbrev,"",@progbits
    62  .Ldebug_abbrev0:
    63          .uleb128 0x1
    64          .uleb128 0x11
    65          .byte   0x1
    66          .uleb128 0x25
    67          .uleb128 0xe
    68          .uleb128 0x13
    69          .uleb128 0xb
    70          .uleb128 0x3
    71          .uleb128 0x8
    72          .uleb128 0x1b
    73          .uleb128 0xe
    74          .uleb128 0x11
    75          .uleb128 0x1
    76          .uleb128 0x12
    77          .uleb128 0x7
    78          .uleb128 0x10
    79          .uleb128 0x17
    80          .byte   0
    81          .byte   0
    82          .uleb128 0x2
    83          .uleb128 0x2e
    84          .byte   0x1
    85          .uleb128 0x3f
    86          .uleb128 0x19
    87          .uleb128 0x3
    88          .uleb128 0xe
    89          .uleb128 0x3a
    90          .uleb128 0xb
    91          .uleb128 0x3b
    92          .uleb128 0xb
    93          .uleb128 0x49
    94          .uleb128 0x13
    95          .uleb128 0x11
    96          .uleb128 0x1
    97          .uleb128 0x12
    98          .uleb128 0x7
    99          .uleb128 0x40
   100          .uleb128 0x18
   101          .uleb128 0x2117
   102          .uleb128 0x19
   103          .uleb128 0x1
   104          .uleb128 0x13
   105          .byte   0
   106          .byte   0
   107          .uleb128 0x3
   108          .uleb128 0x34
   109          .byte   0
   110          .uleb128 0x3
   111          .uleb128 0x8
   112          .uleb128 0x3a
   113          .uleb128 0xb
   114          .uleb128 0x3b
   115          .uleb128 0xb
   116          .uleb128 0x49
   117          .uleb128 0x13
   118          .uleb128 0x1c
   119          .uleb128 0xb
   120          .byte   0
   121          .byte   0
   122          .uleb128 0x4
   123          .uleb128 0x24
   124          .byte   0
   125          .uleb128 0xb
   126          .uleb128 0xb
   127          .uleb128 0x3e
   128          .uleb128 0xb
   129          .uleb128 0x3
   130          .uleb128 0x8
   131          .byte   0
   132          .byte   0
   133          .byte   0
   134          .section        .debug_aranges,"",@progbits
   135          .long   0x2c
   136          .value  0x2
   137          .long   .Ldebug_info0
   138          .byte   0x8
   139          .byte   0
   140          .value  0
   141          .value  0
   142          .quad   .Ltext0
   143          .quad   .Letext0-.Ltext0
   144          .quad   0
   145          .quad   0
   146          .section        .debug_line,"",@progbits
   147  .Ldebug_line0:
   148          .section        .debug_str,"MS",@progbits,1
   149  .LASF2:
   150          .string "main"
   151  .LASF1:
   152          .string "/home/takk/tmp"
   153  .LASF0:
   154          .string "GNU C11 6.3.0 20170516 -mtune=generic -march=x86-64 -g -O"
   155          .ident  "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
   156          .section        .note.GNU-stack,"",@progbits
takk@deb9:~/tmp$

ないですね。ジャンプ。

gdb使ってみます。

takk@deb9:~/tmp$ gcc -O -g t.c
takk@deb9:~/tmp$ gdb a.out

いつものようにブレイクしてrun。

(gdb) b main
Breakpoint 1 at 0x660: file t.c, line 9.
(gdb) r
Starting program: /home/takk/tmp/a.out

Breakpoint 1, main () at t.c:9
9       }
(gdb)

mainにはブレイクしました。
ステップ実行します。

(gdb) n
__libc_start_main (main=0x555555554660 <main>, argc=1, argv=0x7fffffffe5c8,
    init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
    stack_end=0x7fffffffe5b8) at ../csu/libc-start.c:325
325     ../csu/libc-start.c: そのようなファイルやディレクトリはありません.
(gdb)
[Inferior 1 (process 1013) exited normally]
(gdb)
The program is not being run.
(gdb)

いきなりないって言われます。何もせずプログラムが終了しました。
デバッグする時は、最適化してはいけないってことですね。

Leave a Reply

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

CAPTCHA