感覚器(SEQ / CMP)による条件分岐——「盲目の爆撃」から「知覚による狙撃」への進化
メモリの中身を見比べて次の命令をスキップする条件分岐が、デジタル生命に「眼(知覚フィードバック)」を与える
Dwarfは何もない空地にも盲目的に爆弾を投げますが、「スキャナー(Scanner)」 は 眼(比較命令 SEQ / CMP) を持っています!
2行目の SEQ.I @3, $4 は、 - 「ポインタ(@3)が指す遠くのマス」と「空っぽの基準箱($4=DAT #0, #0)」を見比べます。 - もし同じ(=ただの空地)なら、次の3行目(MOV 爆撃)をスキップして飛ばす! - もし違う(=敵がいる!)なら、スキップせずに3行目の MOV でそこへ爆弾を撃ち込む!
🎯 やってみよう 1行目(0000 番地)のスキャン歩幅 A(左の数値) が #0 で止まっています。これを #8 に変更して [PLAY] を押し、0400 番地の敵を見つけ出して精密狙撃しましょう!
1. 盲目のDwarf(オープンループ)と眼を持つScanner(クローズドループ)
Step 19〜21で扱った爆撃機Dwarfは、強力ではあるものの「眼(感覚器)」を一切持っていませんでした。そのため、狙った番地が空っぽの荒野(DAT #0, #0)であろうと敵の陣地であろうとお構いなしに、毎回必ず1サイクルを使って『MOV』で爆弾を投げ続けていました。制御工学では、このように外界の状態を観察せず一方的に動作し続ける仕組みを「オープンループ制御(開ループ制御)」と呼びます。
それに対し、このStep 23で登場した『スキャナー(Scanner)』は、比較命令『SEQ(Skip if Equal:同じなら次をスキップ/旧名 CMP)』という「眼」を持っています! ・まず遠くのメモリ番地を覗き見る(Scan)。 ・もしそこが「空っぽの空地(DAT #0, #0)」なら、爆弾を投げる行(MOV)をスキップして時間を節約し、すぐ次の番地の調査へ向かう! ・もしそこが「空地ではない(=敵のコードがある!)」なら、スキップせずに次の行の『MOV』を実行し、発見した敵へピンポイントで爆弾を撃ち込む! このように外界からの情報(フィードバック)に応じて行動を切り替える知的な仕組みを「クローズドループ制御(閉ループ制御)」と呼びます。
[0000] ADD.AB #8, $4 ──► 1. Advance scan pointer by +8
[0001] SEQ.I @3, $4 ──► 2. Compare remote cell (@3) with blank DAT ($4 = [0005])
│
├── If EQUAL (Empty space) ──► SKIP Line 0002! Jump straight to [0003] JMP!
└── If NOT EQUAL (Enemy!) ──► Do NOT skip! Execute [0002] MOV to snipe!
[0002] MOV.I $3, @2 ──► 3. Snipe the detected enemy with a DAT bomb!
[0003] JMP.A $-3, #0 ──► 4. Repeat scan loop2. CPUにおける「条件付きスキップ(Skip-Next)」のアーキテクチャ
高級言語の『if (A == B)』という条件分岐が、機械語のレベルでどのように実現されているかを見てみましょう。 CoreWar(ICWS-94)の比較命令『SEQ.I A, B』は、非常にシンプルかつ美しいルールで動きます。 ・ALUが「Aが指す箱」と「Bが指す箱」の中身を丸ごと(.I修飾子)比較する。 ・もし2つの箱の中身が【完全に一致(Equal)】していたら、通常は『PC + 1』に進むはずのプログラムカウンタを『PC + 2(1行飛ばして2つ下の行)』へと進める! ・もし2つの箱の中身が【不一致(Not Equal)】だったら、通常通り『PC + 1(すぐ下の行)』へ進める。
初期の多くのRISCプロセッサやマイクロコントローラ(PICマイコンやARMの条件実行など)でも、この「条件が満たされたら次の1命令をスキップする(Skip Next Instruction)」というハードウェア機構が広く採用されてきました。なぜなら、次の1命令(今回の『MOV』)を無効化(NOP化)するだけで済むため、ジャンプ先番地を複雑に計算するよりも回路が単純になり、わずか1行の追加で「敵がいないときはMOVを飛ばし、敵がいるときだけMOVを実行する」というif文が完成するからです。
3. スキャン歩幅の最適化と「自己スキャン回避」
今回のミッションでは、1行目(0000番地)のスキャン歩幅を『#0』から『#8』に変更することで、0004番地のポインタ(初期値 #388)に8を足して『396』にし、ポインタ自身の番地(0004)からの相対距離『0004 + 396 = 0400番地』に潜んでいた敵を1発で見つけ出して狙撃しました。
注意深い方は、2行目の『SEQ.I @3, $4』の右オペランド『$4』が、0001番地から4つ下にある『0005番地(DAT.F #0, #0)』を指していることに気づいたでしょう。なぜポインタ箱である 0004番地(DAT.F #0, #388)ではなく、わざわざ 0005番地に「もう1つの空っぽのDAT #0, #0」を用意して見比べているのでしょうか? それは、アリーナの大半を占める「誰もいない空地」の中身が『DAT.F #0, #0』だからです! 0005番地に置いた「無垢な空地の見本(DAT #0, #0)」と遠くのマス(@3)を見比べることで、相手がほんの少しでも命令や数値を置いていれば「見本と違う=敵発見!」と100%確実に検知できるのです。
🔒 MISSION CLEAR で講義ノートの全編が解放されます
上段の実験シミュレーターでミッションを達成すると自動的に全編がアンロックされます。(下のボタンから今すぐ全文を先に読むことも可能です)