アセンブラ短歌

「アセンブラ短歌」は五・七・五・七・七の三十一バイト(みそひとバイト)から成る 機械語コードでプログラムを書いてみるという近未来の文化的趣味であり,近年, 国内のハッカー間で密かなブームが起きています.

例えば,以下のような感じです.

タイトル:「夏休み」(詠み人:坂井弘亮)

6a 00 58 50 40
68 79 61 6d 61 50 40
6a 08 5a 5b 40
68 57 61 6b 61 54 40
59 cd 80 58 58 58 c3

目次

概要

■ アセンブラ短歌とは何か?

例えば以下のようなアセンブラのプログラム「waka.S」があるとします. これはLinux/x86向けの文字列出力プログラムで,main()関数のみからできています. 具体的には,各種レジスタの設定をして int 0x80 によって write システムコールを 呼ぶことで,文字列を出力しています.

        .global main
main:
        mov     $0x616b6157, %eax
        push    %ebx
        push    %eax
        mov     $4, %edx
        mov     $1, %ebx
        mov     $4, %eax
        mov     %esp, %ecx
        int     $0x80
        pop     %eax
        xor     %eax, %eax
        pop     %ebx
        ret
このプログラムは以下のようにしてアセンブルし実行することができます.
$ gcc waka.S -o waka
$ ./waka
Waka$ 
生成された実行ファイル「waka」を逆アセンブルすると,以下のようになります.
$ objdump -d waka
08048404 <main>:
 8048404:       b8 57 61 6b 61          mov    $0x616b6157,%eax    ←5バイト(1句目)
 8048409:       53                      push   %ebx              ┐
 804840a:       50                      push   %eax              │←7バイト(2句目)
 804840b:       ba 04 00 00 00          mov    $0x4,%edx         ┘
 8048410:       bb 01 00 00 00          mov    $0x1,%ebx           ←5バイト(3句目)
 8048415:       b8 04 00 00 00          mov    $0x4,%eax         ┐←7バイト(4句目)
 804841a:       89 e1                   mov    %esp,%ecx         ┘
 804841c:       cd 80                   int    $0x80             ┐
 804841e:       58                      pop    %eax              │
 804841f:       31 c0                   xor    %eax,%eax         │←7バイト(5句目)
 8048421:       5b                      pop    %ebx              │
 8048422:       c3                      ret                      ┘
└───┘     └──────┘        └───────────┘
    ↑                ↑                            ↑
命令の配置先     機械語コード                  ニーモニック
アドレス
機械語コードが,ちょうど 5バイト・7バイト・5バイト・7バイト・7バイトの位置で区切ることができる ようになっています. これは偶然ではなく,実はそうなるようにうまく命令の順番を調整してwaka.Sを 作成しています.

機械語コードを抽出してそのように並べると,以下のようになります.

b8 57 61 6b 61
53 50 ba 04 00 00 00
bb 01 00 00 00
b8 04 00 00 00 89 e1
cd 80 58 31 c0 5b c3
このように機械語コードを5・7・5・7・7にそろえることができるプログラムを 「アセンブラ短歌」と呼んでいます.正確には「機械語コード短歌」なのですが, まあアセンブラ短歌のほうが通じがよくていいかなと. 命令の区切りが5・7・5・7・7の区切りにそろっているのがポイントで, 命令が句をまたがないようにします.

ちなみに機械語コードのサイズが5・7・5・7・7になっている必要はありません (つまり,5命令だけで5・7・5・7・7が構成されている必要はありません). まあほんとはそうなっていればかっこいいのですが,さすがにそこまですると プログラミングの幅が狭まってしまうので.

ということで,例えば上の例では1句目は5バイトの1命令ですが, 2句目は1バイト命令が2つと5バイト命令が1つで計7バイト,というように なっています.そういう構成でも構いません.

■ 約束ごとは?

あくまで芸術作品なので, まあこれといった決まりがあるわけではなく詠みたいひとが自由に作品を作れば いいだけです.文字列出力に限る必要も無く,様々な作品が考えられると思います.

ただ暗黙の了解として,以下のようなものがあります.

これは,そうしないと例えば文字列出力とかでは57577中に出力文字列を 詰め込んでそこを出力するだけとか,実際には実行されないような命令を詰め込んで 先頭でジャンプして全部すっとばしてしまうみたいな方法がほとんどになって しまって,工夫の余地というか面白さが無くなってしまうかなーと思うからです.

■ たくさんの文字を出力できればいいのですか?

アセンブラ短歌は,単なるショート・コーディングの技術を競うものではありません. もちろん出力文字数の多さなどを競ってもいいのですがそれだけではなく, 私は,以下のような観点で詠んでみるのもいいかなあと思っています.

いかに趣向を凝らすか? ということを競うのが,アセンブラ短歌の面白いところです.

そもそも文字列出力に限る必要もありません. 三十一バイトでウィンドウをオープンしてみるとか, シェル起動してみるとか,いろいろ考えられることでしょう.

■ 「味わい深さ」ってなんですか?

例えば以下は「Wakayama」という8文字を出力するアセンブラ短歌です.

        .global main
main:
/*2*/   push    $0
/*1*/   pop     %eax  /* EAXをゼロクリア */
/*1*/   push    %eax
/*1*/   inc     %eax  /* EAXを+1 */

/*5*/   push    $('y'|'a'<<8|'m'<<16|'a'<<24)
/*1*/   push    %eax
/*1*/   inc     %eax  /* EAXを+1 */

/*2*/   push    $8
/*1*/   pop     %edx
/*1*/   pop     %ebx
/*1*/   inc     %eax  /* EAXを+1 */

/*5*/   push    $('W'|'a'<<8|'k'<<16|'a'<<24)
/*1*/   push    %esp
/*1*/   inc     %eax  /* EAXを+1 (これでEAXが4になる) */

/*1*/   pop     %ecx
/*2*/   int     $0x80 /* writeシステムコールを呼び出す */
/*1*/   pop     %eax
/*1*/   pop     %eax
/*1*/   pop     %eax
/*1*/   ret
8文字の出力はアセンブラ短歌ではそれほど難しくはありません.が,上のリストは EAXにシステムコール番号の「4」という値を格納するのに直接代入するのではなく, ゼロ設定してからinc命令を4回呼び出して1ずつ増加させることで実現しています.

そして,バイト列を抽出すると以下のようになります.

6a 00 58 50 40
68 79 61 6d 61 50 40
6a 08 5a 5b 40
68 57 61 6b 61 54 40
59 cd 80 58 58 58 c3
4つのinc命令が各句の最後にあるため,各句が「40」という一定のバイトで終了して いることに注目してください.つまり,韻を踏んでいるわけです. ニーモニックを見ると1〜4句目ではpush/pop/inc命令のみが使われており, push-pop-push-inc, push-push-inc のようなかろやかなリズムも感じられます.

また命令調整のための安易なnopも無く,きちんと三十一バイトに収まっていることは, 完成度が高い作品だと言うこともできるでしょう.

こういうのが「味わい深い」ということかなあ,なんて思います. 他にも上の句(五・七・五)と下の句(七・七)で処理の内容が区切られていたりすると, それはそれで味わい深いかなあと思います.

もちろんこれらのことに技術的な意味はまったくありませんが,アセンブラ短歌は 芸術作品なのですから,味わい深ければいいのです.

句の先頭バイトを並べるとそれはまた別の意味になるとか, 命令にリズムを持たせて躍動感を演出するとか, 命令をすべて表示可能な文字コードで占めるようにするとか, といったものでもいいでしょう.

で,そういった「工夫した点」「味わい深い点」を紹介して自慢するのが, アセンブラ短歌の醍醐味です.

■ その他の約束ごとは?

あくまで競技でなく芸術作品なので,基本的に自由です.

例えば字余りしてもいいかとは思います.ただ完成度という点ではちと低くなって しまうかなあと思います.もっとも安易な字余りではなくそれにより「味わい深さ」 が増すような前向きのものならば,それはそれでいいのかなあとも思います.

三十一バイトが関数化されていることや,main()関数であることも,必須では ありません.そのようにきれいにまとまっていれば完成度は高いかもしれませんが, まあこのへんも詠み人の自由でいいかなと.

スタックの使いかたが(開放済み領域を使うとかで)ズルしているとか, レジスタの使いかたが(関数呼び出しで保存すべきものを保存してないとかで)ズル しているとか,main()がゼロを返していないので異常終了するとか, そもそも目的の処理後にcore dumpしてしまうとかいうのも, (まあ完成度は低いと思われてしまうかもしれませんが), それを補って余りあるような味わい深さとかがあれば, それはそれでいいかなあと思います.


メールは kozos(アットマーク)kozos.jp まで