MC6800のプログラミングテクニック(13) 多バイトの+1/-1操作をinc/decで行う
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
ディスカッション
コメント一覧
まだ、コメントがありません