Category Archives: 7-1.ファイル・アーカイブ

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


アニメ『メルクストーリア -無気力少年と瓶の中の少女-』

小瓶娘のよく分からない会話の語尾が愉快です。
語尾がほぼ「~ですよ。」なんですが、~ですか?という質問でさえも、「~ですよ?」となるので、質問しているようには聞こえず、自分の主張を、強く言い聞かせてるようにしか、聞こえません。
こんな困った人とは、本来会話は成り立たないハズなのですが、登場する人たちはちゃんと、この小瓶娘と会話できてます。愉快ですよ。

今回も、やっぱりエンディアンです。
htonlですが、目的がネットワークのバイトオーダーの変換なので、64bitがありません。
man htonl確認。

takk@deb9:~/tmp$ man htonl
BYTEORDER(3)               Linux Programmer's Manual              BYTEORDER(3)

名前
       htonl,  htons,  ntohl, ntohs - ホストバイトオーダーとネットワークバイト
       オーダーの間で値を変換する

書式
       #include <arpa/inet.h>

       uint32_t htonl(uint32_t hostlong);

       uint16_t htons(uint16_t hostshort);

       uint32_t ntohl(uint32_t netlong);

       uint16_t ntohs(uint16_t netshort);

説明
       htonl()  関数は unsigned integer hostlong  を  ホストバイトオーダーから
       ネットワークバイトオーダーに変換する。

       htons()   関数は  unsigned  short integer hostshort を ホストバイトオー
       ダーからネットワークバイトオーダーに変換する。

       ntohl()  関数は unsigned integer netlong を  ネットワークバイトオーダー
       からホストバイトオーダーに変換する。

       ntohs()   関数は  unsigned short integer netshort を ネットワークバイト
       オーダーからホストバイトオーダーに変換する。

似たような処理をしてくれるもので、bswapマクロの方は、64bit/32/16bitのエンディアン変換ができるようになっています。

BSWAP(3)                   Linux Programmer's Manual                  BSWAP(3)

NAME
       bswap_16, bswap_32, bswap_64 - reverse order of bytes

SYNOPSIS
       #include <byteswap.h>

       bswap_16(x);
       bswap_32(x);
       bswap_64(x);

DESCRIPTION
       These  macros  return  a value in which the order of the bytes in their
       2-, 4-, or 8-byte arguments is reversed.

RETURN VALUE
       These macros  return  the  value  of  their  argument  with  the  bytes
       reversed.

自作のエンディアン変換アセンブラは、htonlというより、エンディアン変換するだけの処理なので、名前をbswap風に変えてみます。

takk@deb9:~/tmp$ cat -n my-bswap.s
     1          .text
     2          .globl my_bswap_32
     3  my_bswap_32:
     4          mov %rdi, %rax
     5          bswap %eax
     6          ret
     7
takk@deb9:~/tmp$

my_bswap_32にしました。

ついでに64bit版や16bit版も作ってみましょう。

takk@deb9:~/tmp$ cat -n my-bswap.s
     1          .text
     2          .globl my_bswap_64
     3  my_bswap_64:
     4          mov %rdi, %rax
     5          bswap %rax
     6          ret
     7
     8          .globl my_bswap_32
     9  my_bswap_32:
    10          mov %rdi, %rax
    11          bswap %eax
    12          ret
    13
    14          .globl my_bswap_16
    15  my_bswap_16:
    16          mov %rdi, %rax
    17          bswap %ax
    18          ret
takk@deb9:~/tmp$

では、アセンブル。

takk@deb9:~/tmp$ as -o my-bswap.o my-bswap.s
my-bswap.s: Assembler messages:
my-bswap.s:17: Error: operand type mismatch for `bswap'
takk@deb9:~/tmp$ vi my-bswap.s
takk@deb9:~/tmp$

なぜか16bit版がエラーになりました。 16bitの変換に関しては次回に確認するので、今回はあきらめます。
my_bswap_32を削除してアセンブルすると、問題なくオブジェクトができました。

takk@deb9:~/tmp$ as -o my-bswap.o my-bswap.s
takk@deb9:~/tmp$ 

呼び出し側のmain.cはこのように改造。

takk@deb9:~/tmp$ cat -n main.c
     1  #include <stdio.h>
     2  #include <stdint.h>
     3  uint64_t my_bswap_64(uint64_t);
     4  uint32_t my_bswap_32(uint32_t);
     5  int main()
     6  {
     7          uint64_t a=0x11223344aabbccdd;
     8          uint32_t b=0x12345678;
     9          uint16_t c=0x1234;
    10          a = my_bswap_64(a);
    11          printf("%16llx\n",a);
    12          b = my_bswap_32(b);
    13          printf("%08x\n",b);
    14  }
takk@deb9:~/tmp$

printf中%xは64bitの場合、%llxで指定します。16桁なので%16llxとしています。

実行すると、

takk@deb9:~/tmp$ gcc main.c my-bswap.o
takk@deb9:~/tmp$ ./a.out
ddccbbaa44332211
78563412
takk@deb9:~/tmp$

64bit、32bit、問題なく、エンディアン変換できました。