使い方
プログラムの最初に
1 1 1
と書いておけば、以降変数1は定数1として使える
0 0 1 0 1 0 0 0
これで、「H」が出力できる。頑張って並べれば「Hello, world!」が書ける
基本的な計算
### X <- !Y X Y Y ### X <- Y X Y Y X X X ### X <- Y & Z X Y Z X X X ### X <- Y | Z s Y Y t Z Z X s t ### X <- Y ^ Z s Y Y t Z Z s s Z t t Y X s t
こんだけだとどう書いたらQuineができるのかよく分からない。もっと複雑なのを書くためにマクロを作る
フラグによって動作を変える命令が重要で、これを使わないと頭がおかしくなる。
## copy_flag_if(d, s, f) # d = f ? s : d = (s & f) | (d & ~f) x f f y d x x s f d x y ## copy_reg_if(d, s, f) copy_flag_if(d[0], s[0], f) copy_flag_if(d[1], s[1], f) ... copy_flag_if(d[7], s[7], f)
条件付インクリメントとかは
## inc_if(d, f) copy_reg(tmp, d) inc(tmp) copy_reg_if(d, tmp, f)
インクリメントってどうやるの?
## inc(r) set_flag(c) # c 0 0 # キャリー clear_flag(d) # d 1 1 # not キャリー ## 半加算器 s r0 r0 s s c t r0 d d r0 c c d d r0 s t ## 半加算器 s r1 r1 s s c t r1 d d r1 c c d d r1 s t ... s r7 r7 s s c t r7 d d r7 c c d d r7 s t
ROM の構成
ROMっていうのは16bitから8bitへのデコーダとかそんなもんですから、入力と出力を決めてやれば頑張ってNANDだけで書けるわけです。
でも、Quineで使うROMはそのROMのプログラム自体を出力できなければいけません。ようするに規則的に作らないといけないというわけです。
インターフェースはこんな感じにします
## ROM ## ## ADDR_BUS 16bit in ## DATA_BUS 8bit out # ここでADDR_BUSに適当な値を設定する copy_reg(ADDR_BUS, PC) # ROMのコードを記述する ... # ここまで実行が終わると DATA_BUS に結果が入ってる copy_reg(VALUE, DATA_BUS)
ROMの各セルは次のように作ります
## ## if (ADDR_BUS-- == 0) { ## DATA_BUS = ROM[addr] ## } ## dec(ADDR_BUS, carry) copy_reg_if(DATA_BUS, 'H', carry)
これで、値'H'の入ったROMができました。これをたくさん並べれば好きなだけ大きなROMが作れます。
つづく