MC6800のプログラミングテクニック(13) 多バイトの+1/-1操作をinc/decで行う

BASICMASTER, 昔のパソコン

6800にはメモリを直接操作する命令があり、便利に使える。下記の11種がそれだ。

  • CLR/COM/NEG/DEC/INC/ROL/ROR/ASL/ASR/LSR/TST

シフト・ローテート命令は多倍長の乗除算に使えるし、他の命令もちょっとした操作でAccA,Bを壊さなくて済むのが良い。


多倍長のINCは簡単

1バイトの変数がメモリ上にあるとき、これを+1/-1するのは簡単だ。


	inc M (あるいはdec M)

2バイト変数の+1は分岐が必要。Acc経由にするよりも高速である。10 or 16cycle, 8bytes。


	inc M+1		; 6 3
	bne L1		; 4 2
	inc M		; 6 3
L1:

Acc経由だとLD/ADD/STが2回必要で、対象がダイレクトページでも18cycle,12bytes必要。ダイレクトページ以外なら、22cycle,16bytes。


	ldab M+1	; 3 2
	ldaa M		; 3 2
	addb #1		; 2 2
	adca #0		; 2 2
	stab M+1	; 4 2
	staa M		; 4 2
L1:


多倍長のDECは面倒

INCは0になるのを検出すれば良かったのだが、DECは難しい。減算する前に0であるか確認する必要がある(減算後に$FFか確認しても良いが、0の方が楽)。

2バイトの例。減算する前にtst命令で0かどうかを確認。16 or 22cycle, 11bytes必要。それでも Accが壊れないのと、メモリ使用量が少ないのがメリット。


	tst M+1		; 6 3
	bne L1		; 4 2
	dec M		; 6 3
L1:	dec M+1		; 6 3

Accを壊して良いのなら tstの代わりにldaが使えて、3cyc,1bytes減る。



3バイト以上だとさらにややこしい。例として4バイトの場合、59cycle, 28bytes.


	tst M+3		; 6 3
	bne L1		; 4 2
	tst M+2		; 6 3
	bne L2		; 4 2
	tst M+1		; 6 3
	bne L3		; 4 2
	dec M		; 6 3
L3:	dec M+1		; 6 3
L2:	dec M+2		; 6 3
L1:	dec M+3		; 6 3
	rts		; 5 1


tstの代わりにldabを使ってみる。50cyc,25bytes.


	ldab M+3	; 3 2
	bne L1		; 4 2
	ldab M+2	; 3 2
	bne L2		; 4 2
	tst M+1		; 3 2
	ldab L3		; 4 2
	dec M		; 6 3
L3:	dec M+1		; 6 3
L2:	dec M+2		; 6 3
L1:	dec M+3		; 6 3
	rts		; 5 1



IXを壊して良いなら2バイトずつ処理でき、短くて速い。38cycle, 15bytes。

IXが$FFFFであるかのチェックにCPX #$FFFFではなく、inxを使うと2バイト減るが1cycle遅くなる。MC6800のinx/dex/ins/desは遅い。


	ldx M+2		; 4 2
	dex		; 4 1
	stx M+2		; 5 2
	cpx #$FFFF	; 3 2
	bne ret		; 4 2
	ldx M		; 4 2
	dex		; 4 1
	stx M		; 5 2
ret:	rts		; 5 1