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)
かなりスッキリしました。


コメント