TVアニメ『寄宿学校のジュリエット』オープニング映像
アニメ『寄宿学校のジュリエット』
シェイクスピアのロミオとジュリエットのように、お互い対立する勢力にいるので、結ばれてはいけない恋です。でも恋人同士であることを知られないようにするって、さぞ楽しいでことでしょう。ラブコメ楽しいです。
ではアセンブラの続きです。
今回は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)
かなりスッキリしました。
コメント