掛け算
1~100 を足すプログラムの比較ルールを示した際に、「n*(n+1)/2 の公式を使えば速い」というのは無し、と書きました。
ただし、別の例題として、両者同じ条件で比較する、という前提であればありだと思います。
目次
1~100の足し算(別ページ)
ブロック転送(別ページ)
概要
Z80 と 6502 で、n * (n+1) / 2 をやってみましょう。
…と言っても、ほとんど掛け算ルーチンを作るだけですが。
8bit * 8bit = 16bit が必要になります。
実は、これも 16bit レジスタを持つ Z80 に有利な問題。
n の範囲は、1~254 とします。(n+1 で 8bit に収まるように)
クロック計測は、先の問題と同じく、n=100 で行うものとします。
改良案は、ページ下部のコメント欄や、メールで送って下さい。待っています。(SPAM対策アドレス表記使用)
Z80基本
HL = BC * A / 2 を計算します。
LD HL,#0 ; 10 (11)
LD A,#100 ; 7 (8)
LD B,L ; 4 (5)
LD C,A ; 4 (5)
INC C ; 4 (5)
LOOP:
SRL A ; 8 (10)
JR NC,SKIP ; 12 / 7 (13 / 8)
ADD HL,BC ; 11 (12)
SKIP:
JR Z,END ; 12 / 7 (13 / 8)
SLA C ; 8 (10)
RL B ; 8 (10)
JP LOOP ; 10 (11)
END:
SRL H ; 8 (10)
RR L ; 8 (10)
基本的な 8bit 掛け算のプログラムです。2進数の筆算をやっています。
もっと高速な最適化ができそうな気もしますが、やっていません。(投稿お待ちしています)
最終的な結果は HL に入ります。
前処理が 34 クロック
LOOP 以下が、加算が生じた場合 69クロック、生じない場合 62 クロック。
ただし、乗数を2進数で示したときに、一番左の 1 の桁を計算した時点で終了します。
この際、次のループの準備は行わないので、26 クロック速くなります。
ここでは、乗数を 100 で計算しています。2進数では 0110 0100 。
なので、7回ループして、加算が3回生じます。
69*3 + 62*4 - 26 = 429 で、計算部分で 429クロックということですね。
最後に、後処理として 2 で割っています。これが 20クロック。
総計で、483 クロックです。
6502基本
Z80 の HL をゼロページの 0 1 に、BC を 2 3 に、A を 4 に割り当てたベタ移植です。
LDA #0 ; 2
STA >0 ; 3
STA >1 ; 3
STA >2 ; 3
LDA #101 ; 2
STA >3 ; 3
LDA #100 ; 2
STA >4 ; 3
LOOP:
LSR >4 ; 5
BCC SKIP ; 3 / 2
CLC ; 2
LDA >1 ; 3
ADC >3 ; 3
STA >1 ; 3
LDA >0 ; 3
ADC >2 ; 3
STA >0 ; 3
SKIP:
LDA >4 ; 3
BEQ END ; 3 / 2
ASL >3 ; 5
ROL >2 ; 5
JMP LOOP ; 3
END:
LSR >0 ; 5
ROR >1 ; 5
前処理に 21クロック
LOOP 内は、加算が生じた場合 45クロック、生じない場合 26 クロック。
終了条件は Z80 版と同じで、最後だけ 12 クロック速くなります。
乗数 100 として、ループ内は 45*3 + 26*4 - 12 = 227 で 227 クロック。
後処理に 10 クロック。
総計で、258 クロックです。MSX に負けます。
このプログラム、とりあえず HL 相当を X Y に持たせる高速化も行ってみましたが、僕の改良では 246クロックで、やはり MSX に負けます。
もっと改良できそうな気もするので、あえて XY は使わない「読みやすい」プログラムを提示しておきます。
次の例題は…ブロック転送