10進表示
目次
6502基本
LDA #>8086 ; 2
STA >0 ; 3
LDA #<8086 ; 2
STA >1 ; 3
LDA #0 ; 2
PHA ; 3
LOOP:
LDA #10 ; 2
JSR DIV ; 6 + 400
ORA #$30 ; 2
PHA ; 3
LDA >0 ; 3
ORA >1 ; 3
BNE LOOP ; 3 / 2
LDX #-1 ; 2
AFTER:
INX ; 2
PLA ; 4
STA DECIMAL,X ; 5
BNE AFTER ; 3 / 2
END:
6502 では、素直にスタックを使用しています。
教科書に乗ってそうなプログラムで、特に説明はいらないかな…
前処理に 15 クロック。
1桁の処理に 22 クロック。
最後は1クロック速くなり、次の処理のために 2 クロックかかります。
つまり、最後は +1 クロック。
後処理に、1桁ごとに 14+400 クロック。400 は除算ルーチンです。
これも最後は 1 クロック速くなります。
15 + 22*4 +1 +414*4 -1 = 1759
総計は 1759 クロックになります。
ひたすら引き算
2014.9.5 追記
「ひたすら引き算する」方法によるプログラム、6502 版も投稿されました。ありがとうございます。
LDY #0 ;2
LDX #<8086 ;2
STX >1 ;3
LDA #>8086 ;2
CPX #<10000 ;2
BCC CHK1000 ;3/2
BNE L10000 ;3/2
CMP #>10000 ;2
BCS L10000 ;3/2
CHK1000:
CPX #<1000 ;2
BCC CHK256 ;3/2
BNE L1000 ;3/2
CMP #>1000 ;2
BCS L1000 ;3/2
CHK256:
CPX #1 ;2
BCS L100 ;3/2
CMP #100 ;2
BCS L100 ;3/2
CMP #10 ;2
BCS L10 ;3/2
ORA #$30 ;2
STA DECIMAL ;4
BNE LAST ;3
SUB16:
STX >2 ;3
LDX #$30 ;2
BNE SSKIP ;3
SLOOP:
STA >1 ;3
INX ;2
LDA >0 ;3
SSKIP:
SBC >2 ;3
STA >0 ;3
LDA >1 ;3
SBC >3 ;3
BCS SLOOP ;3/2
TXA ;2
STA DECIMAL,Y ;5
INY ;2
LDA >0 ;3
ADC >2 ;3
SEC ;2
RTS ;6
L10000:
LDX #<10000 ;2
STX >3 ;3
LDX #>10000 ;2
JSR SUB16 ;6
L1000:
LDX #<1000 ;2
STX >3 ;3
LDX #>1000 ;2
JSR SUB16 ;6
L100:
LDX #<100 ;2
STX >3 ;3
LDX #>100 ;2
JSR SUB16 ;6
L10:
LDX #$30-1 ;2
LOOP:
INX ;2
SBC #10 ;2
BCS LOOP ;3/2
ADC #10+$30 ;2
STA DECIMAL+1,Y ;5
TXA ;2
STA DECIMAL,Y ;5
INY ;2
LAST:
LDA #0 ;2
STA DECIMAL+1,Y ;5
基本的にはZ80からの移植です。
が、もちろん 6502 に特化して高速化している個所はあります。
>0 >1 に被除数を入れているのですが、基本的には被乗数の下位バイトは A に入っていて、>0 は退避用です。
また、前処理の間は上位バイトは X に入っていて、メモリアクセスを出来るだけ少なくしています。
SUB16 ルーチンは、Z80 と違い、16bit 演算ができないため、繰り上がりながら 8bit 演算を繰り返しています。
これは 6502 のお約束。
8bit 演算に収まる 10の位だけは、SUB16 を呼び出さずに計算します。これも Z80 と同じ。
処理速度ですが、非常に厄介なことになります。
Z80版と同じく、条件分岐が多いからひたすら数えるしかない…と言うのは同じなのですが、分岐の形が違うため、非常に多くの「場合わけ」が存在してしまうのですね。
Z80 なら、10000 と比較することで、5桁かどうかわかりました。
でも、6502 は 8bit 演算しかできないので、10000 と比較できません。
上位バイトの比較だけで明らかになる場合と、下位バイトまで比較しないと明らかにならない場合の2通りの速度があります。
これは、「5桁じゃない」と判るのも2通りの速度がある、と言う意味にもなります。
5桁でないなら4桁か? ここでも、処理に入る前に2通りの経路があり、4桁判定に2通りの経路があるため、組み合わせとして4経路。
3桁の場合は8経路… というわけで、クロック数の組み合わせはどんどん増えます。表にしても無意味なくらいに。
というわけで、ここでは Z80 のような速度表を示さず、ただ数えた結果だけを書きます。
8086 を 10 進数に直す場合、何桁の数値かを判定する前処理で 21 クロック。
16bit 演算ルーチンは、数値が n の桁の計算を終了するのに、23*n + 45 クロック。
上位2桁はこのルーチンで計算され、計 274 クロックかかります。
10の位は別のループで計算していて、7*(n+1)-1 クロック。
n=8 で計算することになるので、62 クロックかかります。
それ以外の部分は、4桁の計算の際に限ると、全部で 51 クロック。
21+274+62+51 = 408
総計は 408 クロックになります。