vm2gol v2 製作メモ(3) regチカ(jump)



プログラムといえばループ! ですね(※1)。 ループをやりましょうということで、 jump 命令を追加して regチカをやりましょう。

(※1 ……と書いてはいますが、実際は「次に簡単そうなのは何かな?」と考えて 何をやるのかを決めていました。 スモールステップでやっていきます。 )

regチカ(れぐちか)というのは今勝手に作った言葉で、 電子工作の Lチカのように、 レジスタの値を 0 にしたり 1 にしたりして チカチカするのを愛でるというものです。

BASIC風に書くとこんな感じでしょうか。

10 reg_a に 1 をセット
20 reg_a に 0 をセット
30 GOTO 10

これならすぐできそう。VM の case 式に jump を追加して、

--- a/vgvm.rb
+++ b/vgvm.rb
@@ -30,6 +30,9 @@ class Vm
         n = @mem[@pc + 1]
         @reg_a = n
         @pc += 2
+      when "jump"
+        addr = @mem[@pc + 1]
+        @pc = addr
       else
         raise "Unknown operator (#{op})"
       end

プログラム(@mem の中身)を書き換えます。

--- a/vgvm.rb
+++ b/vgvm.rb
@@ -12,8 +12,10 @@ class Vm
     @reg_c = 0
 
     @mem = [
+      # ★1
       "set_reg_a", 1,
       "set_reg_a", 0,
+      "jump", 0, # ★1 に戻る
       "exit"
     ]
   end

一番最初の set_reg_a のアドレスが 0 なので、 0 にジャンプします。

これを動かすと……

$ ruby vgvm.rb 
#<Vm:0x005609a6b609d0
 @mem=["set_reg_a", 1, "set_reg_a", 0, "jump", 0, "exit"],
 @pc=0,
 @reg_a=0,
 @reg_b=0,
 @reg_c=0>
#<Vm:0x005609a6b609d0
 @mem=["set_reg_a", 1, "set_reg_a", 0, "jump", 0, "exit"],
 @pc=2,
 @reg_a=1,
 @reg_b=0,
 @reg_c=0>
#<Vm:0x005609a6b609d0
 @mem=["set_reg_a", 1, "set_reg_a", 0, "jump", 0, "exit"],
 @pc=4,
 @reg_a=0,
 @reg_b=0,
 @reg_c=0>
#<Vm:0x005609a6b609d0
 @mem=["set_reg_a", 1, "set_reg_a", 0, "jump", 0, "exit"],
 @pc=0,
 @reg_a=0,
 @reg_b=0,
 @reg_c=0>
#<Vm:0x005609a6b609d0
 @mem=["set_reg_a", 1, "set_reg_a", 0, "jump", 0, "exit"],
 @pc=2,
 @reg_a=1,
 @reg_b=0,
 @reg_c=0>
#<Vm:0x005609a6b609d0
 @mem=["set_reg_a", 1, "set_reg_a", 0, "jump", 0, "exit"],
 @pc=4,
 @reg_a=0,
 @reg_b=0,
 @reg_c=0>
#<Vm:0x005609a6b609d0
 @mem=["set_reg_a", 1, "set_reg_a", 0, "jump", 0, "exit"],
 @pc=0,
 @reg_a=0,
 @reg_b=0,
 @reg_c=0>
#<Vm:0x005609a6b609d0
 @mem=["set_reg_a", 1, "set_reg_a", 0, "jump", 0, "exit"],
 @pc=2,
 @reg_a=1,
 @reg_b=0,
 @reg_c=0>
(続く)

@reg_a=1 になったり @reg_a=0 になったりしてますね! jump 命令で1ステップ使うので3拍子になっていますが。

ものすごく原始的なプログラムでものすごく原始的なループが動きました。 すばらしい……(しばしターミナルを眺めて愛でる)。