6800の分岐命令とインタプリタ(ベーシックマスター開発 その31)
MC6800の分岐命令が面倒臭いのは6800の分岐命令(ベーシックマスター開発 その30) | ず@沖縄で書いた。
MC6800でなくても、CPUの扱えるレジスタ長を超えると大小比較は面倒くさくなる。
その面倒臭さを当時のインタプリタはどう扱っていたかを、書き残しておく。
NAKAMOZU Tiny BASIC
比較演算子を構文解析し、下記の数値に置き換える。電大版TinyBASICも同様の処理を行なっている。
EX11 ORAB #1 ; 比較論理演算
FCB $8C ; チェック
EX12 ORAB #2
FCB $8C ; 結果AccB
EX13 ORAB #4 ; > 0000 0001
INX ; = 0000 0010
FCB $C1 ; < 0000 0100
EX14 CLR B ; >= 0000 0011
BSR PKUP ; <= 0000 0110
CMP A #'>' ; <> 0000 0101
BEQ EX11
CMP A #'='
BEQ EX12
CMP A #'<'
BEQ EX13
CLR A
RTS
次に右式-左式を行って、立ったフラグと上記の数値を比較して分岐する。結果は1か0である。
左-右ではなく、右-左なのはインタプリタが素直に左から解釈しているから。左を計算してPSHして、右を計算してTSX/SUBA 1,X/SBCB 0,Xで計算を行なっている。
(NAKAMOZU/電大Tinyは上位バイトがB,下位バイトがAなので、見慣れないとびっくりする)
引き算が左-右ではなく、右-左になっていて逆なので前回記事の分岐表をひっくり返す必要がある。
EXPR BSR EX1
BSR EX14 ; 論理演算チェック
TST B
BEQ RTN8
PSH B
BSR EX1
JSR CPUL ; 演算(再帰的)
LDX CSP ; BAは後の数
SUB A 1,X ; 比較
SBC B 0,X ; 後-前
PUL B
BLT LT ; 論理演算
BGT GT
TST A
BEQ EQ
GT ASR B
EQ ASR B
LT AND B #1
STA B 1,X
CLR 0,X
単に比較する場合と比べて 実行時間は多くかかるが、そもそもインタプリタなので字句解析や構文解析に多大な時間がかかっている。
メモリの節約と実行時間のどちらを取るかの判断で、メモリ節約を選んだのだろう。メモリの1バイトは血の1バイト。
GAME言語
構文解析中に関係演算子が見つかったら、左式-右式を計算して 0 or 1 を返している。左-右なので、前回記事の表の通りに分岐命令を書けば良い。
NTB/電大 Tiny BASICよりメモリは食うが、高速である。
LT PULA
LESS BSR SUB
BLT TRUE
FALSE CLRA
CLRB
RTS
FALSEで分岐するかTRUEで分岐するか
2バイトが一致しないことの比較(!=)をして、0か1を返すサブルーチンを考えよう。
メモリを節約することを考えると、引き算して一致した場合は0になるのでこれをそのままFalseとして返すと良い。するとコードはこうなる。
SUBB 下位バイト
SBCA 上位バイト
BNE True
TSTB
BNE True
RTS // ここに来る時は AccA,B==0 なのでそのままFalseとして返す
True LDAB #1
CLRA
RTS
論理を逆転して、一致しなければラベルに分岐、一致してTの場合はスルーして通り抜けるようなコードになる。
では、全パターンそれでうまくいくかというとそうではない。一致の比較だと、抜けてきた時にAccAB=0なので、これを利用したい。するとこうなる。
True1,2を分けているのは、2番目のBNEで分岐したときはAccA==0なので、Bだけクリアすれば良いから。
この場合は、スルーした時がTになる。
SUBB 下位バイト
SBCA 上位バイト
BNE True1
TSTB
BNE True2
INCB // ここに来る時は AccA,B==0 なので、+1して返す
RTS
True1 CLRA
True2 CLRB
RTS
比較の条件によって、最適なパターンが異なるので非常にややこしいです。
メモリを節約したい場合は、実行時間を考えずにTrue/Falseの分岐先を作ってそこに分岐すればOKです。KUMAJIRIのK-CPUはそのパターン。
ディスカッション
コメント一覧
まだ、コメントがありません