版を指定して表示しています。
理由が無い限り、最新版の閲覧をお願いします。

ブロック転送

1~100 を足すプログラムで、先に改良が進んだのは 6502 でした。

一時期 6502 の方が速そうに思えたので、「Z80 に花を持たせようと 16bit 演算&ループを使う題材にしたのだけど」と書いたところ、「Z80 に花を持たせるなら、ブロック転送はどうでしょう」という意見がありました。


目次

1~100の足し算(別ページ)

掛け算(別ページ)

概要

Z80基本

6502基本

速度比較



概要

ブロック転送か…ちょっとずるい気もしますが、実用的な例題でもあります。

ブロック転送とは、連続したメモリ内容を、別のアドレスにコピーすることを言います。


別記事書きましたが、ゲームを作る際には「画面表示タイミング」を気にしながら画面を書き変える必要がありました。

実際の VRAM と同じサイズのメモリを用意しておき、そこを仮想画面としてゲームの画面を作っておきます。

そして、画面が垂直帰線期間(何も表示しない時間)になった時に、そのメモリ内容を VRAM に転送するのです。


ファミコンでは、スプライトの設定がちょうど 256byte に収まる設計だったため、256バイトを一気に転送したりしました。

6502 は 256 バイト以上のメモリを一括して扱うのが苦手なのですが、ファミコンのハードはうまく設計されていて、256バイトの転送で済むようにしてあるのですね。


MSX では Z80 から直接 VRAM を操作することはできなかったのですが、例題ですので


・400H から 200H byte を、600H にブロック転送する


を考えてみます。


改良案は、ページ下部のコメント欄や、メールで送って下さい。待っています。(SPAM対策アドレス表記使用)


Z80基本

Z80ではこんな感じ。


	LD HL,#400H ; 10 (11)
	LD BC,#200H ; 10 (11)
	LD DE,#600H ; 10 (11)
	LDIR ; 21 / 16 ( 23 / 18)

LDIR は、ブロック転送命令です。HL から BC バイトを DE に転送します。

1バイト転送ごとに、 21 (23) クロックかかりますが、最後の1バイトだけは 16 (18) バイトで終わります。


速度は、前処理が 33クロック、LDIR が…1命令で 511*23 + 18 = 11771クロック、合計 11804 クロックですね。


これは、おそらく改良の余地のないプログラム。

(実質的に LDIR 命令1つで終わるプログラムで、他の部分はその前処理にすぎないため)


6502基本

6502ではこうです。


	LDX #0 ; 2
LOOP:
	LDA 400H,X ; 4
	STA 600H,X ; 5
	LDA 500H,X ; 4
	STA 700H,X ; 5
	DEX ; 2
	BNE LOOP ; 3 / 2

6502 にはブロック転送命令もないですし、256 を超えるアドレスの扱いも苦手です。

そこで、512バイトを 256バイト 2つにわけて、ループの中で同時に転送しています。


転送方法も、A レジスタに読み出して、改めて別の個所に書き込むだけ。地味な作業です。


ループ内が 23 クロックで、最後だけ1クロック少ないです。ループ回数は 256回。前処理は2クロックです。


2 + 23*256 - 1 = 5889 クロック。


速度比較

6502 は 5889 クロック。2倍すると 11778 クロックで、これが MSX のクロック相当での実時間になります。

Z80 は11804 クロックなので、僅差でファミコンの勝ちです。


ただ、これも実質的には「同程度の速度」と言ってよいと思います。転送量が 256 の倍数、という 6502 に扱いやすい題材だったので高速化できたけど、そうでなければ 6502 のプログラムはややこしいことになって、MSX に負けるでしょう。


たぶん Z80 をこれ以上高速化する方法は無いと思います。ほぼ1命令で終わっているから。

(ページ作成 2014-08-03)
第1版 …他の版 最新版

前記事:掛け算     戻る     次記事:ランダムアクセス
トップページへ

-- share --

0000

-- follow --




- Reverse Link -