セキュリティキャンプに参加できるようになったのはいいけど低レイヤもx64も全然わからんので最近その辺りを勉強してます。
「低レベルプログラミング(翔泳社)」にnasmのマクロプロセッサで素数判定しようと言う節があったのでそれに倣ってフィボナッチ数列を書いてみます。
fibo.asm
global _start section .data %assign limit 0x14 fibo: dw 0, 1 %assign i 0 %assign j 1 %rep limit %assign k i+j dw k %assign i j %assign j k %endrep section .text ret_fibo: xor rax, rax mov ax, [fibo + 2*rdi] ;dwで数列の要素を書き込んだので2*rdiでアクセスする。 ret _start: mov rdi, 0xd ; 0xd(=13)番目の値を取得する call ret_fibo ;exitシステムコール mov rdi, rax mov rax, 0x3c syscall
$ nasm -felf64 -g -o fibo.o fibo.asm // -gオプションを付けないとデバック時にシンボルが見つからないって怒られるぞい $ ld -o fibo fibo.o $ ./fibo $ $? 233: command not found
%rdiにフィボナッチ数列の0xd番目の要素を格納し,$?
により終了ステータスとして値を取り出しています。
0xdをハードコードしているのは本質から外れたコードを除きたかったからで、決して読み込みのルーチンを書くのが面倒だったりそんな技術力が無かったりしたわけではありません。
プリプロセッサにより置換された部分を抜粋してみます。
nasm -E
でプリプロセッサによりシンボルが展開されたソースを確認することができます。
$ nasm -E fibo.asm ... fibo: dw 0, 1 %line 12+1 fibo.asm dw 1 %line 12+0 fibo.asm dw 2 dw 3 dw 5 dw 8 dw 13 dw 21 dw 34 dw 55 dw 89 dw 144 dw 233 dw 377 dw 610 dw 987 dw 1597 dw 2584 dw 4181 dw 6765 dw 10946 %line 13+1 fibo.asm [section .text] ret_fibo: xor rax, rax mov ax, [fibo + 2*rdi] ret _start: ...
マクロについて
置換
nasmのマクロプロセッサでは以下のようにして置換を定義することができます。
%define hoge 0x0+0x1 %xdefine bar 0x0+0x1 %assign foo 0x0+0x1 mov rax, hoge mov rax, bar mov rax, foo
$ nasm -E test.asm %line 1+1 macro.asm %line 5+1 macro.asm mov rax, 0x0+0x1 mov rax, 0x0+0x1 mov rax, 1
上の実行結果から見てわかるように、%assignは%defineと異なり遅延評価されません。
for文
%rep n
forがかける!!!すごい!...のか?