vm2gol v2 製作メモ(6) if文っぽい条件分岐



前回 comparejump_eq を使っていきなりカウンタを作ってしまいましたが、 この2つがあれば、

a = 0
b = 0
if a == b
  c = 2
else
  c = 3
end
a = 4

みたいな普通の if 文っぽいことができそうです。ちょっとやってみましょう。

BASIC風に書くとこう。

10 set_reg_a 0
20 set_reg_b 0
30 compare
40 jump_eq 70

# else
50 set_reg_c 3
60 jump 80

# then
70 set_reg_c 2

# endif
80 set_reg_a 4

a と b が等しい場合は c に 2 をセットし、 そうでない場合は c に 3 をセットし、 どちらの場合でもその後に a に 4 をセットする。

else 節の後に then 節、という順番が慣れない感じですが、 なんかできそうですね。機械語にしてみます。

# 06_if.vge.yaml

[
  # 0
  "set_reg_a", 0,
  # 2
  "set_reg_b", 0, # ここを書き換えて動作確認する
  # 4
  "compare",
  # 5
  "jump_eq", 11,
  # 7
  "set_reg_c", 3,
  # 9
  "jump", 13,
  # 11
  "set_reg_c", 2,
  # 13
  "set_reg_a", 4,
  # 15
  "exit"
]

まずはこれをそのまま実行します。

$ ruby vgvm.rb 06_if.vge.yaml
pc( 0) | reg_a(0) b(0) c(0) | zf(0)
pc( 2) | reg_a(0) b(0) c(0) | zf(0)
pc( 4) | reg_a(0) b(0) c(0) | zf(0)
pc( 5) | reg_a(0) b(0) c(0) | zf(1) … a == b なので zf == 1 になった
pc(11) | reg_a(0) b(0) c(0) | zf(1) … then 節にジャンプした
pc(13) | reg_a(0) b(0) c(2) | zf(1) … then 節を実行した
pc(15) | reg_a(4) b(0) c(2) | zf(1) … 最後に reg_a に 4 をセットした
exit

いいですね。では、プログラムを書き換えて a == b とならない場合を試してみます。

"set_reg_b", 0,

"set_reg_b", 1,

に書き換えて実行。

$ ruby vgvm.rb 06_if.vge.yaml
pc( 0) | reg_a(0) b(0) c(0) | zf(0)
pc( 2) | reg_a(0) b(0) c(0) | zf(0)
pc( 4) | reg_a(0) b(1) c(0) | zf(0)
pc( 5) | reg_a(0) b(1) c(0) | zf(0) … a != b なので zf == 0 のまま
pc( 7) | reg_a(0) b(1) c(0) | zf(0) … ジャンプせずに次の命令へ進んだ
pc( 9) | reg_a(0) b(1) c(3) | zf(0) … else 節を実行した
pc(13) | reg_a(0) b(1) c(3) | zf(0) … then 節を飛び越えて最後にジャンプした
pc(15) | reg_a(4) b(1) c(3) | zf(0) … 最後に reg_a に 4 をセットした
exit

いいですね!