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

TVアニメ【RELEASE THE SPYCE】第二弾PV

アニメ『RELEASE THE SPYCE』

テンポが良くてすごく面白いです。最終話まで継続視聴予定です。

ずっとエンディアン変換のアセンブラを作っていて、気がつきました。
C言語とディスアセンブルしたコードを対比していけば、アセンブラの修得も早そうです。
さっそく学習を始めることにします。普段使いのPCはPentiumなので、x64アセンブラを覚えていくことにします。

takk@deb9:~/tmp$ cat /proc/cpuinfo | grep model.name
model name      : Intel(R) Pentium(R) CPU G4400 @ 3.30GHz
takk@deb9:~/tmp$

では、ベースのソースとして、空のmain.cを作成。

takk@deb9:~/tmp$ cat -n t.c
     1  int main()
     2  {
     3
     4  }
takk@deb9:~/tmp$

アセンブルします。

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    $0, %eax
    14          popq    %rbp
    15          .cfi_def_cfa 7, 8
    16          ret
    17          .cfi_endproc
    18  .LFE0:
    19          .size   main, .-main
    20          .ident  "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
    21          .section        .note.GNU-stack,"",@progbits
takk@deb9:~/tmp$

変数定義を追加してみましょう。

takk@deb9:~/tmp$ cat -n t1.c
     1  int main()
     2  {
     3          int a;
     4  }
takk@deb9:~/tmp$

そして、アセンブル。比較。

takk@deb9:~/tmp$ gcc -S t1.c
takk@deb9:~/tmp$ diff t.s t1.s
1c1
<       .file   "t.c"
---
>       .file   "t1.c"
takk@deb9:~/tmp$

変数を定義しただけでは、何も変わらないということですね。

次は、変数の初期化を追加。

takk@deb9:~/tmp$ cat -n t2.c
     1  int main()
     2  {
     3          int a;
     4          a = 50;
     5  }
takk@deb9:~/tmp$

アセンブルして、差分を見ます。

takk@deb9:~/tmp$ gcc -S t2.c
takk@deb9:~/tmp$ diff t.s t2.s
1c1
<       .file   "t.c"
---
>       .file   "t2.c"
12a13
>       movl    $50, -4(%rbp)
takk@deb9:~/tmp$

ロカール変数の領域である-4(%rbp)に、50を格納する命令が増えています。
次は、if文を使います。

takk@deb9:~/tmp$ cat -n t3.c
     1  int main()
     2  {
     3          int a;
     4          a = 50;
     5          if(a == 50){
     6                  a = 30;
     7          }
     8  }
takk@deb9:~/tmp$

アセンブル、比較。

takk@deb9:~/tmp$ gcc -S t3.c
takk@deb9:~/tmp$ diff t.s t3.s
1c1
<       .file   "t.c"
---
>       .file   "t3.c"
12a13,17
>       movl    $50, -4(%rbp)
>       cmpl    $50, -4(%rbp)
>       jne     .L2
>       movl    $30, -4(%rbp)
> .L2:
takk@deb9:~/tmp$

比較命令であるcmplが50という値と、ローカル変数-4(%rbp)の値を比較しています。
jneは、not equalsなので、不一致なら.L2へジャンプする命令ですね。

コメント

タイトルとURLをコピーしました