C言語でx64アセンブラを覚える(その5)


『転生したらスライムだった件』

スライムはゲームとかだと最弱モンスターですが、このアニメは、最強モンスターのようです。とにかくチート主人公です。最初はスライムってことであまり真剣に見る気はなかったんですが、めちゃ面白いですねえ。

今回は、三項演算子のアセンブラです。

三項演算子は一行にif文が書けて分かりやすいですね。まあ例えばこんな感じで。

takk@deb9:~/tmp$ cat tt.c
#include <stdio.h>
int main()
{
        int a=0;
        printf("%s\n", a == 0 ? "zero" : "not zero");

        a = 100;
        printf("%s\n", a == 0 ? "zero" : "not zero");
}
takk@deb9:~/tmp$ gcc tt.c
takk@deb9:~/tmp$ ./a.out
zero
not zero
takk@deb9:~/tmp$

では、三項演算子をアセンブラコードにすると、効率的なんでしょうか。

t.cがif文、t1.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$ cat -n t1.c
     1  int main()
     2  {
     3          int a=10;
     4          int b;
     5          b = a == 10 ? 100 : 200;
     6  }
takk@deb9:~/tmp$

t.cのアセンブラは、前も見ましたね。

takk@deb9:~/tmp$ gcc -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          pushq   %rbp
     9          .cfi_def_cfa_offset 16
    10          .cfi_offset 6, -16
    11          movq    %rsp, %rbp
    12          .cfi_def_cfa_register 6
    13          movl    $10, -4(%rbp)
    14          cmpl    $10, -4(%rbp)
    15          jne     .L2
    16          movl    $100, -8(%rbp)
    17          jmp     .L3
    18  .L2:
    19          movl    $200, -8(%rbp)
    20  .L3:
    21          movl    $0, %eax
    22          popq    %rbp
    23          .cfi_def_cfa 7, 8
    24          ret
    25          .cfi_endproc
    26  .LFE0:
    27          .size   main, .-main
    28          .ident  "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
    29          .section        .note.GNU-stack,"",@progbits
takk@deb9:~/tmp$

t1.cもアセンブラにして比較すると、

takk@deb9:~/tmp$ gcc -S t1.c
takk@deb9:~/tmp$ diff t.s t1.s
1c1
<       .file   "t.c"
---
>       .file   "t1.c"
16c16
<       movl    $100, -8(%rbp)
---
>       movl    $100, %eax
19c19
<       movl    $200, -8(%rbp)
---
>       movl    $200, %eax
20a21
>       movl    %eax, -8(%rbp)
takk@deb9:~/tmp$

三項演算子のアセンブラでは、ローカル変数へ直接値を格納せずに、一度eaxレジスタへ格納してからローカル変数へ格納しています。
eaxレジスタを使う分、三項演算子のニモニックの方が一行多いです。
1行多いからといって処理時間が長くなるとは限りませんが、レジスタを無駄に使っているようにも見えます。

Leave a Reply

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

CAPTCHA