Z80 には10進数を仮想的に扱うための命令 DAA があります。これは、数値演算後の結果を、無理矢理10進数的に補正するという命令です。例えば 0x12 + 0x99 とすると、通常は結果が 0xAB になりますが、直後に DAA を実行すると 0x11 CF=1 となります。これは 12 + 99 = 111 と結果として同じになります。これを BCD表記と言います。
この DAA による疑似10進数演算が何が便利かと言えば、数値を文字列に変換するのがラクという事につきます。普通にレジスタに 123 が格納されているとしたら、下位から順番に÷10 の余りを表示して行く事になります。Z80 で÷10が如何に困難か分かりますでしょうか。以前、この問題に対して Twitter で skyriver さんに大変素晴らしいコードを提示して頂きましたのでご紹介します。
;--------------------------------------------------------------この処理は正確には10で割っていないのですが、256 に対して誤差が 1 未満になる計算なので、正しい答えが返る…との事です。すいません、このルーチンの細かい部分は内容を掴んでいません(汗)。興味のある方は是非こちらのブログで詳細を確認してみてください。
; 数値を10で割る by skyriver @wcinp
; B ÷ 10 = H 商 ... Acc 剰余
; 破壊: F
;--------------------------------------------------------------
CMNDiv10::
ld a, b
or 00000001b
rra
adc a, b
ld h, a
rrca
rrca
rrca
rrca
add a, h
ccf
sbc a, h
inc a
and 0x0F
ld h, a
add a, a
add a, a
add a, h
cpl
rlca
adc a, b
ret
今は DAA を使った BCD計算で処理しているため、幻の凄いルーチンになっています。この素晴らしい処理でもそれなりに時間がかかるのは理解出来ますよね。
これに対して BCD 表記であれば、4ビットマスクで値を取り出すだけです。下位4ビットであれば and %00001111 だけですし、上位4ビットであっても RRCA RRCA RRCA RRCA として4ビットを下位に持ってくるだけです。
さて、この DAA は Acc しか補正してくれません。そのため、16ビットや 32ビットの計算に対して BCD補正を行うためには、ちょっと処理を追加する必要があります。下記は私が使っているサブルーチンとなります。
;--------------------------------------------------------------
; BCD 32bit 数値加減算処理
; HLDE = BCD 32bit数値 00000000 - 99999999
; Acc = 加算値 / 減算値 00 - 99
; out: HLDE 演算結果
;--------------------------------------------------------------
BCDSub32::
ex de, hl
call BCDSub16
ex de, hl
ret nc
ld a, 1
jr BCDSub16
BCDAdd32::
ex de, hl
call BCDAdd16
ex de, hl
ret nc
ld a, 1
; jr BCDAdd16
;--------------------------------------------------------------
; BCD 16bit 数値加減算処理
; HL = BCD 16bit数値 0000 - 9999
; Acc = 加算値 / 減算値 00 - 99
; out: HL 演算結果
;--------------------------------------------------------------
BCDAdd16::
add a, l
daa
ld l, a
ld a, h
adc a, 0
daa
ld h, a
ret
BCDSub16::
push bc
ld c, a
ld a, l
sub c
daa
ld l, a
pop bc
ld a, h
sbc a, 0
daa
ld h, a
ret
ご活用頂ければ幸いです。
![[GUSCIO ITALY(グッシオ イタリー)] リュック バックパック キャリーオンバッグ A4 PC収納 メンズ 198001](https://m.media-amazon.com/images/I/41jvtvaZZGL._SL160_.jpg)
コメント