【お知らせ】プログラミング記事の投稿はQiitaに移行しました。

Brainf*ckトランスレータ (4) ループ

前回に引き続きBrainf*ckのトランスレータを見ていきます。

Brainf*ckでは変数の指すメモリの中身が0以外の間だけ回るループがあります。

# while (*(char *)esi) { ... }
start_loop:
    cmpb $0, (%esi)
    jz end_loop
    # ...
    jmp start_loop
end_loop:

cmp命令で0と比較して、一致した場合(jz)はend_loopに飛んで抜けます。jmpは無条件でstart_loopに飛びます。

ループが複数ある場合、ラベル(start_loop, end_loop)に別の名前を付ける必要があります。連番を振れば簡単そうですが、ループがネストすると厄介です。

相対ラベル

ラベルを局所化するテクニックとして相対ラベルがあります。数字のみのラベルが相対ラベルとして扱われます。参照元から見て前(f)か後(b)かをラベルの接尾辞に添えて指定します。相対ラベルは重複しても構いません。

※前・後の方向については次のセクションで取り上げます。

0:
    cmpb $0, (%esi)
    jz 0f # ↓方向に0:を探す
    # ...
    jmp 0b # ↑方向に0:を探す
0:

前・後

前か後かという表現はパーサの進行方向を基準としています。パーサはプログラムを先頭から見ていくため、画面での下が前に相当します。

後
↓
↓
↓
前

直感的に判断すると画面での上が前のように思えてしまうため、慣れが必要な表現です。

ネスト

ループがネストする場合、ネストレベルを相対ラベルの値に割り当てます。うまくペアができていることを確認してください。

0:
    cmpb $0, (%esi)
    jz 0f
1:
        cmpb $0, (%esi)
        jz 1f
            # ...
        jmp 1b
1:
    jmp 0b
0:

上記では読みやすいようにインデントしています。Pythonとは異なり、インデントに文法的な意味はありません。