WRSLTでベンチして

(New:1998/9/2 Update:1998/12/3)
BASICベースでページ0のRAMに書き込みを行う場合、合法的に行うにはBIOSのWRSLTを使うしかないでしょう(BIOSのENASLTではページ0のスロットを切り替えられません)。 ただ、大量にデータを書き込みたい場合、WRSLTはスロット切り替えが絡むため、処理が重くなる事が予想されます。 しかも1バイト書き込む毎にWRSLTを呼ぶわけで。
実は数年前、ビーバーはWRSLTで数キロバイトのデータを書き込むプログラムをこさえたのですが、その処理に秒単位で時間がかかった思い出があるのでした。

※この段落には、デスネタが含まれています(^_^;)。
1998年、Baboo! JAPANの伝言板でWRSLT症候群が猛威(?)を振るっていた。
「WRSLTで大量書き込みしたらどれくらい時間がかかるのか?」
ビーバーは数年前の記憶に突き動かされるものを感じ、「せっかくだから試してみよう」。

というわけで、2つのケースに分けて、WRSLTで大量データの書き込みにかかる時間を測ることにしました。


1つ目は、ページ0のRAM(16KB分)を特定の値(0)で埋めるプログラムです。 WRSLT で1バイトずつ0を書き込むようにしました。

ソース

※一部コメントを省いています。
;=======================================
;BIOS
WRSLT:	EQU	0014H
;WORK AREA
RAM0SA:	EQU	0F341H;ページ0ノ RAM ノ スロットアドレス(ヨウ FDD)
;=======================================
;MAIN
	ORG	0D000H;プログラム カイシ アドレス
	LD	HL,00000H;カキコミ カイシ アドレス
	LD	BC,04000H;カキコム リョウ
	LD	E,0;カキコム アタイ(ベツニ 0デナクテモ イインダケド)
LOOP:
	LD	A,(RAM0SA)
	PUSH	BC
	CALL	WRSLT
	EI
	POP	BC
	INC	HL
	DEC	BC
	;BC == 0?
	LD	A,B
	OR	C
	JP	NZ,LOOP
	;
	RET

結果

※FS-A1STによる。
2つ目は、ページ2からページ0のRAMへ、16KB分ブロックコピーするプログラムです。 やはり、WRSLTで1バイトずつ書き込んでいます。
実際にはこのようにブロックコピーする事が多いのではないかと思い、このプログラムを作りました。

ソース

※一部コメントを省いています。
;=======================================
;BIOS
WRSLT:	EQU	0014H
;WORK AREA
RAM0SA:	EQU	0F341H;ページ0ノ RAM ノ スロットアドレス(ヨウ FDD)
;=======================================
;MAIN
	ORG	0D000H;プログラムノ スタートアドレス
	LD	BC,04000H;コピーリョウ
	LD	DE,08000H;コピーモト アドレス
	LD	HL,00000H;コピーサキ アドレス
LOOP:
	LD	A,(DE)
	PUSH	DE
	LD	E,A
	LD	A,(RAM0SA)
	PUSH	BC
	CALL	WRSLT
	EI
	POP	BC
	POP	DE
	INC	HL
	INC	DE
	DEC	BC
	;BC == 0?
	LD	A,B
	OR	C
	JP	NZ,LOOP
	;
	RET

結果

※FS-A1STによる。

両プログラムとも、実行にあたっては、BASICからUSR関数で呼び出し、呼ぶ直前から戻ってきた直後の時間を測りました。

機種や割り込みの使用状態等によって、多少の違いは出るかもしれませんが、他の機種でも大体同じ結果になると思います(MSX2+ 以下の機種では、標準モードと同じかそれに近い値が出ると思います)。

ソースについて: WRSLTは、必ずDI(割り込み禁止)状態で帰ってくるので、今回は帰ってきたら直ちにEI(割り込み許可)するようにしました。 でも、書き込み中は割込み禁止状態でも構わないのであれば、ソース中のEI(Z80の場合、M1サイクル込みで5ステート)を省けば、少しは高速化できるかもしれません(でも、たかが知れてると思います。 Z80でも、(5×16384)/3570000 = 約0.02秒短くなるだけだし)。
また、今回は、転送量が奇麗な数字(256バイト単位とか)になるとは限らないという前提で作ったので(あるいはビーバーの技術不足で)、転送量チェックの部分がやや汚くなっているかも知れませんが、ここも場合によっては、少し高速化できるかもしれません。

少しはWRSLT症候群患者の参考になるでしょうか(^_^;)?


※実際に動かしてみたい方は、このファイルを解凍して出てくるファイルを使ってください。
テキストを入れるのが面倒だったので(ごめん)、生成されるファイルについて、ここで簡単に説明させて頂きます。
拡張子「.NLA」がソースファイルです。
拡張子「.BAS」がBASICプログラムです。 実行してしばらく待つと結果が出てきます。 多分MSX1でも動きますが、RAM容量は64KB以上必要で、かつFDD(フロッピーディスクドライブ)も必要です(RAMのスロットアドレスを簡単に取得するため。 詳しくはこちら)。
(1998/12/3) A to Cさんのホームページにある不定期日記を見ていたところ、ページ0のRAMにかかわる、より高速なブロックコピーの方法がありました。 以前baboo! 伝言版に書いた、僕らの書き込みに対するレスになっているみたいなのですが…(^_^;)。
簡単に説明すると、あらかじめページ0のRAMにLDIR/RETとか書いておき、そこをインタースロットコールするという方法です。 いや、一本取られましたわ。 さすが A to Cさん!
※詳しくは、A to Cさんのホームページにある、不定期日記の1998/10/12の部分を読みましょう。
※baboo! 掲示版でも既に、該当部分にA to Cさんが突っ込みを入れてました。

その後、A to Cさんに確認したところによると、この方法でインタースロットコール前には、DIしておくべきとのことでした。
この方法でもそうですが、ページ0に対してインタースロットコール/リード/ライトする場合は、基本的にDIしなければならないんだそうです(つまり、前からあるサンプルも、WRSLT前にDIしていないので、実はやばかったと(^_^;))。
※ページ0がBIOS以外のものになっている時に、割り込みが発生するとやばいからですね。

また、

インタースロットコールでの割り込みの変化は不定です。 その時のスロット状態によって、DIされたり保存されたりします。
とのことでした。

A to Cさん、アドバイスありがとうございました。m(_ _)m


MSXの適当手帳 MSX駅 西山駅