MC6800のプログラミングテクニック(19) AccABと0の比較

BASICMASTER, 昔のパソコン

Amsterdam Compiler Kit の生成する中間言語(EM code)では、Top of Stack と0を比較し、ToSに0,1を入れる命令がある。

tlt,tle,teq,tne,tge,tgt がそれだ。6800では ToSはAccABに持つので、要するにAccABと0を比較して、AccABに0か1を入れれば良い。

どうするのが良いか考えてみよう。

tne命令 (AccAB!=0なら、AccAB=1)

AccABが0かどうかは、aba / adca #0 で わかる。AccAB=0 なら、AccA=0, Z=1 になり、AccAB!=0 なら AccA!=0, Z=0 になる。

negaはAccA=0ならC=0, AccA!=0ならC=1である。

組み合わせて下記のコードになる。12cycle, 7bytes。


	aba
	adca #0
	clrb
	nega
	rolb
	clra

素直に分岐で書くとこうなる。AccAB=0のときは何もしない。10 or 12cycle, 10bytes。


	tstb
	bne true
	tsta
	beq false
true:	ldab #1
	clra
false:


teq命令 (AccAB==0なら、AccAB=1)

tneと逆の命令である。teqと同じ発想で書いてみる。suba #1で、AccA==0のときだけC=1にする。negがsuba #1になった分だけ長くなる。

12cycle, 8bytes。


	aba
	adca #0
	clrb
	suba #1
	rolb
	clra

素直に分岐で書くとこうなる。バイト数を数える気が起こらないほど長い。bra nextの代わりに、fcb $85 (bita #)を書いて1バイト縮める技もあるが、現代風じゃないよな。

10 or 16 or 18cycles, 11bytes。


	tstb
	bne false
	tsta
	bne false
true:	incb
	bra next:
false:	clrb
	clra
next:


tlt命令 (AccAB<0なら、AccAB=1)

AccAB<0 かどうかは、AccAのbit7でわかる。bit7==1ならAccB=1, bit7==0ならAccB=0にすれば良い。 シフト・ローテート命令でAccAのbit7を、AccBのbit0に移動するだけである。 8cycle, 4bytes.


	clrb
	asla
	rolb
	clra


tge命令 (AccAB>=0なら、AccAB=1)

tltとは逆にAccAのbit7の反転を AccBのbit0に移動する必要がある。Cの反転命令があると良いのだが(8080にはあるのに!)、無い袖は触れないのでeorで反転する。

eor命令の分だけ長くなった。10cycle, 6bytes.


	clrb
	eora #$80
	asla
	rolb
	clra

tgt命令 (AccAB>0なら、AccAB=1)

gt/le は、AccBの状態も見ないといけないので厄介である。素直に分岐で書くとこうなる。長いなあ。10 or 18 or or 24 cycle, 15bytes.

bne true / tstb / beq false2 は、 aba / adca #0 / beq false が良いか?


	tsta
	bgt true
	blt false
	tstb
	beq false2
true:	ldab #1
	clra
	bra next
false:	clrb
false2:	clra
next:


tle命令 (AccAB<=0なら、AccAB=1)

tgtとほぼ同じ。10 or 18 or or 24 cycle, 15bytes.


	tsta
	blt true
	bgt false
	tstb
	bne false
true:	ldab #1
	clra
	bra next
false:	clrb
false2:	clra
next:



tgt、tle はなんとかならんかな。

符号を反転して(nega / negb / sbca #0)、tlt / tge に変換する方法を思いついたが、6cycle, 4bytes増えるので、14cyc, 8byte と 16cycle, 10bytesになる。

分岐よりはマシだが長いなあ。