伝説の爆撃機「Dwarf」の4行解剖——ポインタ演算と間接投射の完全調和
これまでに学んだ「ADD・MOV・JMP・DAT・@ポインタ」が1つの生命体として結晶化した古典的名作
第4章では、いよいよ本物のバトル用プログラム(Warrior)を解剖します! まずはこれまでに学んだ4つの要素が完璧に合体した伝説の爆撃機 「Dwarf(ドワーフ)」 の完成形を観察しましょう:
1. 0000: ADD.AB #4, $3 ➔ 3つ下の宛先メモ(0003番地)のB値に 4 を足す。 2. 0001: MOV.I $2, @2 ➔ 0003番地の DAT 爆弾を、宛先メモ(@2)が指す場所へ投下! 3. 0002: JMP.A $-2, #0 ➔ 0000番地へ戻って繰り返す(結果、4マスおきに次々と爆弾が落ちる!)。 4. 0003: DAT.F #0, #0 ➔ 宛先メモ 兼 投げるデータ爆弾。
🎯 やってみよう(編集不要) [STEP] を繰り返すか [PLAY] を押して、4マスおき(0007, 0011, 0015番地…)に次々と DAT 爆弾が投下される様子を観察しましょう!
1. 4行に凝縮された「戦う状態機械」の完成形
第4章の最初となるStep 19では、A. K. デュードニーが1984年の初代CoreWar論文で「Impの好敵手」として発表した歴史的プログラム『Dwarf(ドワーフ)』の完成形をステップ実行で解剖しました。
Dwarfのコードはわずか4行(0000〜0003番地)しかありません。しかしその4行には、あなたが第1章から第3章までの18ステップで積み上げてきた知識のすべてが、1つの無駄もなく完璧な歯車として噛み合っています。 ・1行目(0000):『ADD.AB #4, $3』 ➔ ポインタ演算器(3つ下の0003番地のB値に、毎周 4 を足して狙いを進める) ・2行目(0001):『MOV.I $2, @2』 ➔ 間接投射砲台(2つ下の0003番地のDAT爆弾を、0003番地のポインタが指す遠くの番地へ投下する) ・3行目(0002):『JMP.A $-2, #0』 ➔ 循環心臓部(2つ上の0000番地へ戻り、3サイクルで1発の爆撃ループを永久に繰り返す) ・4行目(0003):『DAT.F #0, #0』 ➔ 宛先ポインタ 兼 弾薬庫(最初は0、ループごとに 4, 8, 12... と増える)
┌──► [0000] ADD.AB #4, $3 ──(1. Increments [0003].B: +4, +8, +12...)──┐
│ [0001] MOV.I $2, @2 ──(2. Fires [0003] to 0003 + [0003].B)──────┼──► 💥 [0007], [0011], [0015]...
└─── [0002] JMP.A $-2, #0 ◄─(3. Loops back to 0000 every 3 cycles) │
[0003] DAT.F #0, #0 ◄─(4. Dual Role: Target Pointer & Bomb!)────┘2. 0003番地「DAT」が演じる驚異の一人二役(ポインタ兼弾薬)
Dwarfの設計で最もエレガント(芸術的)な部分は、4行目(0003番地)の『DAT』の使われ方にあります。2行目の『MOV.I $2, @2』という命令の左右のオペランド($2 と @2)をよく見てください。 ・左のAオペランド『$2』は、「何を投げるか(コピー元)」を指定しています。0001番地から2つ下($2)なので、『0003番地のDAT箱そのもの』を爆弾として拾い上げています。 ・右のBオペランド『@2』は、「どこへ投げるか(コピー先ポインタ)」を指定しています。同じく2つ下(@2)にある『0003番地のDAT箱のB値』を宛先メモとして読み取り、その番地へ爆弾を飛ばしています。
つまり、0003番地のたった1つの『DAT』箱が、「狙う番地を記憶するポインタ変数」と「敵に投げつけるDAT爆弾のテンプレート」という一人二役を同時にこなしているのです! そのため、1発目に0007番地へ着弾する爆弾の中身は『DAT #0, #4』になり、2発目に0011番地へ着弾する爆弾の中身は『DAT #0, #8』になります。DATの中身の数字が4だろうが8だろうが、踏んだ敵が即死する『DAT爆弾』としての威力は全く同じであるため、ポインタ箱と弾薬箱をわざわざ2つに分ける必要がなく、コードを最小の4行に圧縮できているのです。
3. なぜDwarfは一周して戻ってきても自分を爆撃しないのか?
もう1つ、Dwarfには数学的な魔法が隠されています。Dwarfは3サイクルごとに4マスずつ先(0007, 0011, 0015...)へ爆弾を投げ続けます。やがて800マス(または8,000マス)の円環メモリをぐるりと一周して、自分の本体がいる 0000〜0003 番地の近くへ爆弾が戻ってきたとき、Dwarfは自分で自分を爆撃して自滅してしまわないのでしょうか?
計算してみましょう! 爆弾は必ず『0003番地(ポインタの位置)+ 4の倍数』の番地に落ちます。 800(または8,000)は「4で綺麗に割り切れる数(4の倍数)」です。したがって、メモリを一周して戻ってきたとき、爆弾が落ちるのは 0799 番地(0003 - 4)であり、その次の爆弾は『0799 + 4 = 0003 番地(自分自身のDAT箱の上!)』に着弾します! 自分の命令コードがある 0000, 0001, 0002 番地は綺麗に飛び越され、0003 番地のDAT箱の上に同じDATが上書きされるだけなので、Dwarfは永久に自爆することなく何周でも安全に爆撃を続けられるのです。
🔒 MISSION CLEAR で講義ノートの全編が解放されます
上段の実験シミュレーターでミッションを達成すると自動的に全編がアンロックされます。(下のボタンから今すぐ全文を先に読むことも可能です)