アセンブラのライブラリ(その2)


アニメ『寄宿学校のジュリエット』

シェイクスピアのロミオとジュリエットのように、お互い対立する勢力にいるので、結ばれてはいけない恋です。でも恋人同士であることを知られないようにするって、さぞ楽しいでことでしょう。ラブコメ楽しいです。

ではアセンブラの続きです。
今回はCに埋め込むのではなく、アセンブラソースでライブラリを作成します。
前回のエンディアン変換ソースです。

takk@deb9:~/tmp$ cat -n my_htonl.c
     1  unsigned long my_htonl(unsigned long data)
     2  {
     3          asm("mov -0x8(%rbp),%rax");
     4          asm("bswap %eax");
     5          asm("mov %rax, -0x8(%rbp)");
     6          return data;
     7  }
takk@deb9:~/tmp$

これを-Sオプションでgccするとアセンブラソースが出力されます。

takk@deb9:~/tmp$ gcc -S my_htonl.c
takk@deb9:~/tmp$ cat -n my_htonl.s
     1          .file   "my_htonl.c"
     2          .text
     3          .globl  my_htonl
     4          .type   my_htonl, @function
     5  my_htonl:
     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          movq    %rdi, -8(%rbp)
    14  #APP
    15  # 3 "my_htonl.c" 1
    16          mov -0x8(%rbp),%rax
    17  # 0 "" 2
    18  # 4 "my_htonl.c" 1
    19          bswap %eax
    20  # 0 "" 2
    21  # 5 "my_htonl.c" 1
    22          mov %rax, -0x8(%rbp)
    23  # 0 "" 2
    24  #NO_APP
    25          movq    -8(%rbp), %rax
    26          popq    %rbp
    27          .cfi_def_cfa 7, 8
    28          ret
    29          .cfi_endproc
    30  .LFE0:
    31          .size   my_htonl, .-my_htonl
    32          .ident  "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
    33          .section        .note.GNU-stack,"",@progbits
takk@deb9:~/tmp$

随分と冗長なコードになってますね。
で、次は空のアセンブラソースを作成します。
.textやgloblなどのキーワードは、上の出力アセンブラを参考にします。

takk@deb9:~/tmp$ cat -n my_htonl-asm.s
     1          .text
     2          .globl my_htonl
     3  my_htonl:
     4          pushq %rbp
     5          popq %rbp
     6          ret
     7
takk@deb9:~/tmp$

push/popするだけで何もしないアセンブラのサブルーチンです。
アセンブルできるか確認します。

takk@deb9:~/tmp$ as -o my_htonl.o my_htonl-asm.s
takk@deb9:~/tmp$

問題ないようですので、これをベースに、中身を足していきます。
引数はレジスタrdi、戻り値はraxっぽいので、rdiをraxにコピーした後、直接raxをエンディアン変換(bswap)すればいいですね。

takk@deb9:~/tmp$ cat -n my_htonl-asm.s
     1          .text
     2          .globl my_htonl
     3  my_htonl:
     4          pushq %rbp
     5          movq %rsp, %rbp
     6          mov %rdi, %rax
     7          bswap %eax
     8          popq %rbp
     9          ret
    10
takk@deb9:~/tmp$

アセンブルします。-oでオブジェクトファイルへ出力します。

takk@deb9:~/tmp$ as -o my_htonl.o my_htonl-asm.s
takk@deb9:~/tmp$

生成したオブジェクトファイルを元にアーカイブを作成。

takk@deb9:~/tmp$ ar -rc libmyhtonl.a my_htonl.o
takk@deb9:~/tmp$ 

では、作成したライブラリを指定して、ビルドしてみましょう。

takk@deb9:~/tmp$ gcc main.c -L. -lmyhtonl
takk@deb9:~/tmp$

エンディアン変換できるでしょうか。

takk@deb9:~/tmp$ ./a.out
78563412
takk@deb9:~/tmp$

大丈夫ですね。

では、出来上がったa.outでobjdump -dで出力されるアセンブラも確認してみましょう。

00000000000006b0 <main>:
 6b0:   55                      push   %rbp
 6b1:   48 89 e5                mov    %rsp,%rbp
 6b4:   48 83 ec 10             sub    $0x10,%rsp
 6b8:   48 c7 45 f8 78 56 34    movq   $0x12345678,-0x8(%rbp)
 6bf:   12
 6c0:   48 8b 45 f8             mov    -0x8(%rbp),%rax
 6c4:   48 89 c7                mov    %rax,%rdi
 6c7:   e8 23 00 00 00          callq  6ef <my_htonl>
 6cc:   48 89 45 f8             mov    %rax,-0x8(%rbp)
 6d0:   48 8b 45 f8             mov    -0x8(%rbp),%rax
 6d4:   48 89 c6                mov    %rax,%rsi
 6d7:   48 8d 3d a6 00 00 00    lea    0xa6(%rip),%rdi        # 784 <_IO_stdin_used+0x4>
 6de:   b8 00 00 00 00          mov    $0x0,%eax
 6e3:   e8 78 fe ff ff          callq  560 <printf@plt>
 6e8:   b8 00 00 00 00          mov    $0x0,%eax
 6ed:   c9                      leaveq
 6ee:   c3                      retq

00000000000006ef <my_htonl>:
 6ef:   55                      push   %rbp
 6f0:   48 89 e5                mov    %rsp,%rbp
 6f3:   48 89 f8                mov    %rdi,%rax
 6f6:   0f c8                   bswap  %eax
 6f8:   5d                      pop    %rbp
 6f9:   c3                      retq
 6fa:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

かなりスッキリしました。

Leave a Reply

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

CAPTCHA