2012.4.29
前へ
次へ
ホームページトップへ戻る

復活!CP/M ワンボードマイコンでCP/Mを!
CP/MがTK−80互換のワンボードマイコンの上で復活します
ND80ZVとMYCPU80の上でCP/Mが走ります

[第106回]


●大きなランダムファイルを作る

前回の検討によって、複数のFCBエリアが作成されるような大きなランダムファイルを作成するためには、1ブロックのセクタ数を現行の4セクタから8セクタにしなければだめらしい、ということがわかりました。
しかし現行の仮RAMディスクはもともと12KBしかないところを、さらにAドライブとBドライブに分割しましたから、ドライブの容量はわずか6KBしかありません。
1ブロックが8セクタということは、1セクタが128バイトですから、1ブロックは1KBになります。
ですから、AドライブにもBドライブにも、それぞれ6ブロックしか割り当てることができません。
いくらなんでもそれではテストにならないだろう。
とてもムリ、と思ったのですが。

まてまて。
ここは一番、よーく考えて…。
それで。
よーく考えてみましたら。
いけるじゃないの。
かなりムリムリではありますが、まるで映画のセットみたいなものです。
そこのところだけに注目してテストをするだけならば、ホンモノのようになんとかできそうです。

●テストプログラムの変更

今までのテストではあらかじめ用意したレコードcfータは1バイトの数でした。
しかし今回はもう少し大きい数でテストをしますから、本来と同じ2バイトの数を用意します。
そういうことになりますと、テストプログラムを直さなければなりません。

下は1バイトのレコードb入力していたところを2バイトに変更したテストプログラム(FTST20−2.TXT)のソースリストです。

; BDOS TEST20-2 function22 random write
;2012/3/4 3/7 4/16 4/17 4/27
;
        ORG $8100
        FCALL=$8005
	NMBRTBL=$8300
        FCB=$805C
	FCBR0=$807D
	FCBR1=$807E
	FCBR2=$807F
        DMA=$8080
;
        LD C,16;make file
        LD DE,FCB
        CALL FCALL
        INC A;if FFH?
        JP Z,DFULERR
;
        XOR A
        LD (FCBR2),A
	LD HL,NMBRTBL
	PUSH HL
LOOP:POP HL
	LD A,(HL)
	LD (FCBR0),A
	LD C,A
	INC HL
	LD A,(HL)
	CP FF
	JP Z,CLOSE
	LD (FCBR1),A
	LD B,A
	INC HL
	PUSH HL
;data fill
	LD HL,DMA
	LD D,40
LOOP2:LD (HL),C
	INC HL
	LD (HL),B
	INC HL
	DEC D
	JP NZ,LOOP2
;
	LD C,22;random write
	LD DE,FCB
	CALL FCALL
	OR A
	JP Z,LOOP
	POP HL
	OR 30
	PUSH AF
	LD DE,ERRT
	CALL MSGOUT
	POP AF
	LD E,A
	LD C,02
	CALL FCALL
	RET
;
CLOSE:LD C,10;close
	LD DE,FCB
	CALL FCALL
	INC A;if FFH?
	JP Z,CLOSERR
	LD DE,OK
	JP MSGOUT
;
DFULERR:LD DE,DFULL
	JP MSGOUT
CLOSERR:LD DE,CANTCLS
MSGOUT:LD C,09
        CALL FCALL
        RET
;
CANTOPN:"can'"
        "t op"
        "en!"
        DB 0D
        DB 0A
        DB 24;$
DFULL:"disk"
        " ful"
        "l!"
        DB 0D
        DB 0A
        DB 24;$
CANTCLS:"can'"
        "t cl"
        "ose!"
        DB 0D
        DB 0A
        DB 24;$
OK:"done"
        DB 0D
        DB 0A
        DB 24;$
ERRT:"err "
        DB 24;$
;

データとしてレコード番号を書き込むところも1バイトから2バイトに変更しました。

こちらはFTST20−2.TXTをZASM.COMでアセンブルして得られたアセンブルリストです。

2012/4/27  12:26  ftst20-2.txt
END=81A8
              ; BDOS TEST20-2 function22 random write
              ;2012/3/4 3/7 4/16 4/17 4/27
              ;
                      ORG $8100
                      FCALL=$8005
              	NMBRTBL=$8300
                      FCB=$805C
              	FCBR0=$807D
              	FCBR1=$807E
              	FCBR2=$807F
                      DMA=$8080
              ;
8100 0E16             LD C,16;make file
8102 115C80           LD DE,FCB
8105 CD0580           CALL FCALL
8108 3C               INC A;if FFH?
8109 CA6481           JP Z,DFULERR
              ;
810C AF               XOR A
810D 327F80           LD (FCBR2),A
8110 210083   	LD HL,NMBRTBL
8113 E5       	PUSH HL
8114 E1       LOOP:POP HL
8115 7E       	LD A,(HL)
8116 327D80   	LD (FCBR0),A
8119 4F       	LD C,A
811A 23       	INC HL
811B 7E       	LD A,(HL)
811C FEFF     	CP FF
811E CA5281   	JP Z,CLOSE
8121 327E80   	LD (FCBR1),A
8124 47       	LD B,A
8125 23       	INC HL
8126 E5       	PUSH HL
              ;data fill
8127 218080   	LD HL,DMA
812A 1640     	LD D,40
812C 71       LOOP2:LD (HL),C
812D 23       	INC HL
812E 70       	LD (HL),B
812F 23       	INC HL
8130 15       	DEC D
8131 C22C81   	JP NZ,LOOP2
              ;
8134 0E22     	LD C,22;random write
8136 115C80   	LD DE,FCB
8139 CD0580   	CALL FCALL
813C B7       	OR A
813D CA1481   	JP Z,LOOP
8140 E1       	POP HL
8141 F630     	OR 30
8143 F5       	PUSH AF
8144 11A481   	LD DE,ERRT
8147 CD6D81   	CALL MSGOUT
814A F1       	POP AF
814B 5F       	LD E,A
814C 0E02     	LD C,02
814E CD0580   	CALL FCALL
8151 C9       	RET
              ;
8152 0E10     CLOSE:LD C,10;close
8154 115C80   	LD DE,FCB
8157 CD0580   	CALL FCALL
815A 3C       	INC A;if FFH?
815B CA6A81   	JP Z,CLOSERR
815E 119D81   	LD DE,OK
8161 C36D81   	JP MSGOUT
              ;
8164 118181   DFULERR:LD DE,DFULL
8167 C36D81   	JP MSGOUT
816A 118E81   CLOSERR:LD DE,CANTCLS
816D 0E09     MSGOUT:LD C,09
816F CD0580           CALL FCALL
8172 C9               RET
              ;
8173 63616E27 CANTOPN:"can'"
8177 74206F70         "t op"
817B 656E21           "en!"
817E 0D               DB 0D
817F 0A               DB 0A
8180 24               DB 24;$
8181 6469736B DFULL:"disk"
8185 2066756C         " ful"
8189 6C21             "l!"
818B 0D               DB 0D
818C 0A               DB 0A
818D 24               DB 24;$
818E 63616E27 CANTCLS:"can'"
8192 7420636C         "t cl"
8196 6F736521         "ose!"
819A 0D               DB 0D
819B 0A               DB 0A
819C 24               DB 24;$
819D 646F6E65 OK:"done"
81A1 0D               DB 0D
81A2 0A               DB 0A
81A3 24               DB 24;$
81A4 65727220 ERRT:"err "
81A8 24               DB 24;$
              ;
CANTCLS      =818E  CANTOPN      =8173  CLOSE        =8152  
CLOSERR      =816A  DFULERR      =8164  DFULL        =8181  
DMA          =8080  ERRT         =81A4  FCALL        =8005  
FCB          =805C  FCBR0        =807D  FCBR1        =807E  
FCBR2        =807F  LOOP         =8114  LOOP2        =812C  
MSGOUT       =816D  NMBRTBL      =8300  OK           =819D  

●テストデータを作成します

プログラムを変更しましたから、次はプログラムに読み込ませるレコード番号データを作成します。
前回までのテストではあらかじめ用意したレコードcfータは1バイトの数でした。
今回は2バイトの数のデータを用意します。
ただし、使えるブロックが極端に少ないため、その数値には工夫が必要です。

今回のテストの目的は、複数のFCBが作成されるようなサイズのランダムファイルを作成して、その作られ方を確かめてみたい、というところにあります。
そこで、まずFCBのブロックアローケーションエリアに置かれるレコード番号テーブル(キー配列表と呼ぶことにします)について考えてみます。
レコード番号テーブルについては[第103回]で説明をいたしました。

今回は1ブロックが8セクタとして考えますから、テーブルの構成が変わります。
まず最初のFCBに置かれる番号テーブルは、最初の位置がbO000〜0007、2番目の位置が0008〜000F、というようになって、最後の16番目の位置は0078〜007Fになります(bヘ16進数です)。
次の2番目以降のFCBに置かれる番号テーブルについても同様に考えます。
以下簡単に整理して示します。
最初のFCBを第0とします(エクステントbO)。
中央に書いた数値(16進数)が、そのエクステントのキー配列表に含まれるレコードbナす。

第0FCB 0000〜007F  (00)
第1FCB 0080〜00FF  (01)
第2FCB 0100〜017F  (02)
第3FCB 0180〜01FF  (03)
第4FCB 0200〜027F  (04)
第5FCB 0280〜02FF  (05)
第6FCB 0300〜037F  (06)
第7FCB 0380〜03FF  (07)

後の()の数値は何でしょうか。
よく見るとエクステントbニ同じです。
実は、そのエクステントのキー配列表に含まれるレコードbフ第7ビットから上を取り出して示したものなのです。
たとえば第5FCBでは、0280〜02FFですが、それをビットで表現して、さらに15〜7ビットと6〜0ビットに分けてみます。
0280  000000101 0000000   02FF 000000101 1111111
        (05)      (00)           (05)      (7F)
こうするとレコード番号の上位部分がエクステントbノなりますから、前回お見せしたCPM22Lソースのコメント文の説明に一致します。

さてここからが工夫の必要なところです。
まずディレクトリエリアには少なくとも1ブロックが必要です。
それからテストプログラムをセーブするのにも1ブロックが必要です。
プログラムやデータをセーブする場合、たとえ1セクタしか占有しなくてもそのために1ブロックが占有されます。

すると、Aドライブには6ブロックしかありませんから、ランダムファイルのためには残り4ブロックしか空きがありません。
上に例示しました第0FCB〜第7FCBのなかで4FCBを対象にすることが精一杯です。
さらに、対象にするFCBの中では、同じ1つの位置にあるレコード番号のみを指定しなければなりません(このあたりの意味がよくわからないかもしれません。以下の説明を読んでいっていただければ理解いただけると思います)。

そのように考えてテストデータを選択しました。
選択したレコード番号を、先ほどの表の右に並べました。

第0FCB 0000〜007F  0044 0042 0047 
第1FCB 0080〜00FF  0098 009A 009E 009F
第2FCB 0100〜017F
第3FCB 0180〜01FF  01A2 01A5 01A7
第4FCB 0200〜027F
第5FCB 0280〜02FF
第6FCB 0300〜037F  03B3 03B5 03B6

そしてそのレコード番号をランダムに並べて8300番地からのアドレスに書き込んで、テストデータとしました。
今回のデータは2バイトですから、最初に下位バイト、次に上位バイトの順で書きます。

いつものようにログファイルで説明します。
レコードcfータはZB3BASICのCMコマンドで作成します。

logfile nd80zlog\04271227.txt open

ND80ZVに接続しました
0001 0000 - z
1000 00C3 - 
*** nd80z3 basic ****
>cm 8300
8300 26-a2
8301 0F-01
8302 22-b5
8303 27-03
8304 29-9e
8305 0E-00
8306 11-44
8307 12-00
8308 16-b6
8309 03-03
830A 0D-a7
830B 3F-01
830C 40-9f
830D FF-00
830E CA-9a
830F FF-00
8310 80-b3
8311 10-03
8312 21-a5
8313 00-01
8314 90-98
8315 02-00
8316 01-47
8317 14-00
8318 2B-42
8319 00-00
831A 39-ff
831B 50-ff
831C 08-
>dm 8300,831f
8300  A2 01 B5 03 9E 00 44 00-B6 03 A7 01 9F 00 9A 00  「.オ...D.カ.ァ...D.
8310  B3 03 A5 01 98 00 47 00-42 00 FF FF 08 01 01 10  ウ.・...B...9P....
>

レコードbヘ2バイトで、最初に下位バイト、次に上位バイトの順に書きます。
CMコマンドで入力した結果を、DMコマンドで表示させてみましたが、下位、上位の順ですからちょっと見にくいかと思います。
下に上位、下位の順に直して示します。

01A2
03B5
009E
0044
03B6
01A7
009F
009A
03B3
01A5
0098
0047
0042
FFFF

●CP/Mプログラムを変更します

これまで使ってきましたCP/Mプログラムは仮RAMディスクに対応するために、1ブロックが4セクタと定義していました。
そこのところを1ブロック8セクタに変更しなければなりません。

下はCPM22LのアセンブルリストのBIOS部で定義しているディスクパラメータです。
ここの何箇所かを変更します。

                    	;
  D259  1000          	DPTOP:DEFW	16		;sectors per track from bios.
  D25B  02            		DEFB	2		;block shift.sector in a block 128*2^n
  D25C  03            		DEFB	3		;block mask.sector no. in a block - 1
  D25D  00            		DEFB	0		;extent mask.
  D25E  0B00          		DEFW	11		;disk size (number of blocks-1).
  D260  0F00          		DEFW	15		;directory size.(max file name no.-1)
  D262  8000          		DEFW	80H		;storage for first bytes of bit map (dir space used).
  D264  0000          		DEFW	0
  D266  0000          		DEFW	0		;offset. first usable track number.
                      	;

本当はソースプログラムを変更すべきところなのですが、今回変更するのはプログラムの特定アドレスにある定数部分のみですから、ND80ZVのRAMにロード後のCP/Mマシン語プログラムをCMコマンドで書き換えます。

変更するのは以下の4箇所です。

1)アドレスD25Bの02を03にします。
ここはブロック内のセクタ数を2のn乗で示しています。
4(=22)を8(=23)に変更します。

2)D25Cの03を07にします。
ここも1)と同じです。
ここの値はブロック内のセクタ数−1です。
4−1を8−1に変更します。

3)D25Eの0Bを05にします。
ここの値はディスクの総ブロック数−1です。
12(0CH)−1を6−1に変更します。

4)D260の0Fを1Fにします。
ここの値はディレクトリのFCB数−1です。
FCBは32バイトですから、セクタ当り4個、1ブロックでは32個になります。
ですから32−1=31(1FH)にします。

>cm d25b
D25B 02-03
D25C 03-07
D25D 00-
D25E 0B-05
D25F 00-
D260 0F-1f
D261 00-
D262 80-
>

これで準備はできました。
ちょっと説明が長くなってしまいましたので、テストプログラムの実行につきましては、次回に説明することにいたします。

ワンボードマイコンでCP/Mを![第106回]
2012.4.29upload

前へ
次へ
ホームページトップへ戻る