10進表示

目次

概要

Z80基本

BCD命令ひたすら引き算

6502基本

ひたすら引き算

速度判定


ひたすら引き算

2014.9.1 追記

こちらも投稿。重い割り算よりも「各桁ごとに引き算最大10回」の方が軽いだろう、と言うプログラムです。



	LD DE,8086 ; 10 (11)
	LD HL,-10000 ;  10 (11)
	ADD HL, DE ; 11 (12)
	JR C, L10000 ; 12 / 7 (13 / 8)

	LD HL, -1000 ;  10 (11)
	ADD HL, DE ; 11 (12)
	EX DE, HL ; 4 (5)
	LD DE, DECIMAL ; 10 (11)
	JR C, L1000 ; 12 / 7 (13 / 8)

	INC H ; 4 (5)
	DEC H ; 4 (5)
	JR NZ, L100 ; 12 / 7 (13 / 8)
	LD A, L ; 4 (5)
	CP 100 ; 7 (8)
	JR NC, L100 ; 12 / 7 (13 / 8)
	CP 10 ; 7 (8)
	JR NC, L10 ; 12 / 7 (13 / 8)
	ADD A, 30h ; 7 (8)
	JP LAST ; 10 (11)

SUB16:
	LD A, 30h-1 ; 7 (8)
SLOOP:
	INC A ; 4 (5)
	ADD HL, BC ; 11 (12)
	JR C, SLOOP ; 12 / 7 (13 / 8)
	SBC HL, BC ; 15 (17)
	LD (DE), A ; 7 (8)
	INC DE ; 6 (7)
	RET ; 10 (11)

L10000:
	EX DE, HL ; 4 (5)
	LD DE, DECIMAL ; 10 (11)
	LD BC, -10000 ; 10 (11)
	CALL SUB16 ; 17 (18)
L1000:
	LD BC, -1000 ; 10 (11)
	CALL SUB16 ; 17 (18)
L100:
	LD BC, -100 ; 10 (11)
	CALL SUB16 ; 17 (18)
	LD A, L ; 4 (5)
L10:
	EX DE, HL ; 4 (5)
	LD BC, (30h-1)*256 + 10 ; 10 (11)
LOOP:
	INC B ; 4 (5)
	SUB C ; 4 (5)
	JR NC, LOOP ; 12 / 7 (13 / 8)
	ADD A, 10 + 30h ; 7 (8)
	LD (HL), B ; 7 (8)
	INC HL ; 6 (7)
LAST:
	LD (HL), A ; 7 (8)
	INC HL ; 6 (7)
	LD (HL), 00h ; 10 (11)

プログラムは大きく2つの部分に別れています。

あらかじめ、10進数で何桁の数字になるかを見積もる部分と、実際の10進化処理の部分です。


見積もりが終わったら、10進化処理の途中から始めることで、無駄を省くとともに左詰め処理を行っています。


10進数の各桁ごとに減算を行うため、16bit で減算を行い、引けた回数をメモリに文字で残すルーチンがあります。

SUB16 以下、RET までがそれです。


ただ、常に 16bit で計算を行っていると遅いため、8bit 演算で十分な桁(10の位のみ)は、LOOP 部分で処理を行っています。


まず、この重要ルーチンである SUB16 のクロック数を見積もりましょう。

SUB16 の前処理は 8 クロック、SLOOP のループ部分は 30 クロックです。

「引きすぎた」時に処理が終わりますが、この時はジャンプしないため 5クロック速くなります。


その後、引きすぎた数値を戻す処理と、引けた回数を結果としてメモリに書き込む処理、元のルーチンに復帰する処理が入ります。

これらの後処理が 43 クロック。


SUB16 では、その桁の数値を n とすると、

8 + 30*(n+1)-5 + 43 = 30*n + 76 クロックかかることになります。


では、全体の処理ですが…条件分岐だらけなので、ひたすら数えるしかないです。

条件は「10進での桁数」に依存します。


前処理は、以下のクロック数が必要です。


5桁47クロック
4桁94クロック
3桁112 / 133クロック
2桁149クロック
1桁163クロック

3桁の際に2つ書かれているのは、256以上か未満かで異なるためです。


本処理は、最低以下のクロック数が必要です。


5桁191クロック
4桁146クロック
3桁117クロック
2桁83クロック
1桁26クロック

最低、と言うのは、10の桁のループは最低回数(10の位が 0 となるとき)で、SUB16 内の時間は考慮していないためです。

10の桁のループは、数値が 1 増えるたびに、23クロック増加します。


さて、全体のクロック数を見積もりましょう。

例題では 8086 で4桁です。


上2桁は SUB 16 で処理されますが、その内部の時間は 8 と 0 なので、(30*8+76) + (30*0+76) = 392 クロック。

2の位は、8 なので、8*23 = 184 クロック増加します。


これに、前処理で 94 クロック、本処理で 146 を足します。


94 + 146 + 392 + 184 = 816


総計は、816 クロックです。


うわ、速い (^^;

いろいろ技巧を凝らしたよりも、シンプルに減算するだけの方が速かったか…

次ページ: 6502基本


前ページ 1 2 3 4 次ページ

(ページ作成 2014-08-28)
(最終更新 2014-09-06)
第2版 …他の版 初版

前記事:割り算     戻る
トップページへ

-- share --

2000

-- follow --




- Reverse Link -