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

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

[第102回]


●ファンクションコール22H(ランダムライト)

ファンクションコール22Hは、レコードb指定して、128バイトのデータをそのレコードbノ関連づけられたセクタに書き込みます。
順番によらないランダムな書き込みです。

シーケンシャルファイルに対するレコードの書き込みはファンクションコール15Hを使います([第51回])。
シーケンシャルライトではレコードbフ指定はできません。
シーケンシャルライトも書き込みは1レコード毎に行ないますが、ファイルの先頭から順番に書くことしかできません。

[2012.6.9追記]
このときはそれが常識ですから、そのように書きました。
しかしCP/Mではそのことは常識とは異なっていました。
それについては[第114回]あたりをご参照ください。
[追記ここまで]

これに対してランダムライトはレコードb指定することで、ファイル内の任意の位置に書き込むことができます。
CP/Mで扱うランダムファイルは1レコード128バイトの固定長です。

●テストプログラムFTST20.TXT

ファンクションコール22HのテストプログラムFTST20.TXTのソースリストです。

; BDOS TEST20 function22 random write
;2012/3/4 3/7 4/16 4/17
;
        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)
	CP FF
	JP Z,CLOSE
	LD (FCBR0),A
	LD C,A
	XOR A
	LD (FCBR1),A
	INC HL
	PUSH HL
;data fill
	LD HL,DMA
	LD B,80
LOOP2:LD (HL),C
	INC HL
	DEC B
	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;$
;

ランダムファイルの作成も、基本的にはシーケンシャルファイルの作成と同じ手順です。
シーケンシャルファイルの作成は[第51回]で説明をしました。
最初にファイル名情報が書き込まれたFCBを指定して新規ファイルを作成します。
新規ファイルの作成はファンクションコール16Hを使います。
そのあとファンクションコール22Hでレコードを書き込んで、最後にファンクションコール10Hでクローズします。

このプログラムはテストプログラムですから、あらかじめテスト用にランダムなレコード番号をメモリ(アドレス8300H〜)に書いておいて、それを読み込んで、そのbノしたがってレコードデータを書き込みます。
レコードbヘ本来は2バイトの値ですが、前回説明をしましたディスク容量による制約によって00〜2FH(0〜47)しか使えません(実際はもう少し大きい値も扱うことができます)。
ですからここでは1バイトの値を読み込んで、それをレコードbノしています。
FFHを読み込んだら処理を終わってファイルをクローズします。

レコードbヘFCBの先頭から34バイト目と35バイト目に書き込みます。
また36バイト目には00を書き込みます。
デフォルトではFCBアドレスは805CH(本来は005CH)から始まる36バイトのエリアです。
テストプログラムではその34バイト目〜36バイト目(アドレス807DH〜807FH)に、FCBR0、FCBR1、FCBR2という名前をつけました。
FCBR0にレコードbフ下位8ビットを、FCBR1に上位8ビットを入れます。
FCBR2は常に00にします。

書き込むデータはDMAエリア(デフォルトでは8080H。本来は0080H)の128バイトにあらかじめ書いておきます。
今回はテストですから、確認し易いようにレコードbニ同じ値で128バイト全部を埋めました。

そのように準備してから、Cレジスタに22Hを入れて、システムをコールします。
書き込みに成功するとAレジスタに00が入ります。
失敗したときは、Aレジスタに00以外の値が入るのですが、その意味は「応用CP/M」(村瀬康治著。アスキー出版局)では以下のように説明されています(122頁、126頁)。

03 現在のロジカルエクステントをクローズできない(意味不明)。
05 ディレクトリに空きがなくなった。
06 物理的な範囲を超えてアクセスした。

またインターネットのCP/Mサイト(http://www.seasip.demon.co.uk/Cpm/index.html)のファンクションコール34(22H)の説明ページ(http://www.seasip.demon.co.uk/Cpm/bdos.html#34)では次のように書かれています。

2 Disk full
3 Cannot close extent
5 Directory full
6 Record number out of range

●テストプログラムFTST20.TXTのアセンブル

FTST20.TXTをZASM.COMでアセンブルします。
下はアセンブルの結果作成されたアセンブルリストです。

2012/4/17  16:40  ftst20.txt
END=81A4
              ; BDOS TEST20 function22 random write
              ;2012/3/4 3/7 4/16 4/17
              ;
                      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 CA6081           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 FEFF     	CP FF
8118 CA4E81   	JP Z,CLOSE
811B 327D80   	LD (FCBR0),A
811E 4F       	LD C,A
811F AF       	XOR A
8120 327E80   	LD (FCBR1),A
8123 23       	INC HL
8124 E5       	PUSH HL
              ;data fill
8125 218080   	LD HL,DMA
8128 0680     	LD B,80
812A 71       LOOP2:LD (HL),C
812B 23       	INC HL
812C 05       	DEC B
812D C22A81   	JP NZ,LOOP2
              ;
8130 0E22     	LD C,22;random write
8132 115C80   	LD DE,FCB
8135 CD0580   	CALL FCALL
8138 B7       	OR A
8139 CA1481   	JP Z,LOOP
813C E1       	POP HL
813D F630     	OR 30
813F F5       	PUSH AF
8140 11A081   	LD DE,ERRT
8143 CD6981   	CALL MSGOUT
8146 F1       	POP AF
8147 5F       	LD E,A
8148 0E02     	LD C,02
814A CD0580   	CALL FCALL
814D C9       	RET
              ;
814E 0E10     CLOSE:LD C,10;close
8150 115C80   	LD DE,FCB
8153 CD0580   	CALL FCALL
8156 3C       	INC A;if FFH?
8157 CA6681   	JP Z,CLOSERR
815A 119981   	LD DE,OK
815D C36981   	JP MSGOUT
              ;
8160 117D81   DFULERR:LD DE,DFULL
8163 C36981   	JP MSGOUT
8166 118A81   CLOSERR:LD DE,CANTCLS
8169 0E09     MSGOUT:LD C,09
816B CD0580           CALL FCALL
816E C9               RET
              ;
816F 63616E27 CANTOPN:"can'"
8173 74206F70         "t op"
8177 656E21           "en!"
817A 0D               DB 0D
817B 0A               DB 0A
817C 24               DB 24;$
817D 6469736B DFULL:"disk"
8181 2066756C         " ful"
8185 6C21             "l!"
8187 0D               DB 0D
8188 0A               DB 0A
8189 24               DB 24;$
818A 63616E27 CANTCLS:"can'"
818E 7420636C         "t cl"
8192 6F736521         "ose!"
8196 0D               DB 0D
8197 0A               DB 0A
8198 24               DB 24;$
8199 646F6E65 OK:"done"
819D 0D               DB 0D
819E 0A               DB 0A
819F 24               DB 24;$
81A0 65727220 ERRT:"err "
81A4 24               DB 24;$
              ;
CANTCLS      =818A  CANTOPN      =816F  CLOSE        =814E  
CLOSERR      =8166  DFULERR      =8160  DFULL        =817D  
DMA          =8080  ERRT         =81A0  FCALL        =8005  
FCB          =805C  FCBR0        =807D  FCBR1        =807E  
FCBR2        =807F  LOOP         =8114  LOOP2        =812A  
MSGOUT       =8169  NMBRTBL      =8300  OK           =8199  

●レコード番号表の作成

テストプログラムで読み込むランダムなレコード番号表をメモリ上に作成しておきます。
場所はトランジェントエリアの適当な空いているところを使います。
今回のテストではアドレス8300H〜を使いました。
データの作成はCMコマンドを使うと簡単にできます。

logfile nd80zlog\04171134.txt open

ND80ZVに接続しました
0001 0000 - z
1000 00C3 - 
*** nd80z3 basic ****
>cm 8300
8300 46-26
8301 0F-
8302 32-22
8303 17-27
8304 FF-29
8305 1E-0e
8306 FA-11
8307 4C-12
8308 F7-16
8309 FF-03
830A B3-0d
830B F7-ff
830C EB-
>

データの最後はFFHにします。

●RAMディスクのクリア

今回のテストはRAMディスクをできるだけ空けておいて、空いたところをランダムファイルに最大限割り当てられるようにして行ないます。
今までのテストでAドライブはディスクフルの状態になっていますから、現在の仮RAMディスクのバックアップをとった上で、一旦中味を全部クリアします。

logfile nd80zlog\04171640.txt open

ND80ZVに接続しました
0001 0000 - z
1000 00C3 - 
*** nd80z3 basic ****
>/sv rmdskab2.bin,8800,b7ff
3000(12288)bytes saved
>/ld fille5.bin,8100
loading FILLE5.BIN ...0010(16)bytes loaded,from 8100 to 810F
>jp 8100
>

ZB3BASICにエントリしたあと、
/sv rmdskab2.bin,8800,b7ff[Enter]
と入力してRAMディスク(アドレス8800H〜B7FFH)のバックアップをとりました。
そのあと、
/ld fille5.bin,8100[Enter]
と入力して、RAMディスククリアプログラムをロードして、
jp 8100[Enter]
で、実行しました。
RAMディスククリアプログラムFILLE5.BINは[第37回]で説明をしました。

●プログラムのセーブと実行

/ld ftst20.bin,8100[Enter]
と入力して、FTST20.BINを8100にロードしてから、
jp d233[Enter]
でCP/Mを起動しました。

>/ld ftst20.bin,8100
loading FTST20.BIN ...00a5(165)bytes loaded,from 8100 to 81A4
>jp d233

a>save 1 ftst20.com
a>dir
A: FTST20   COM
a>dir b:
No file
a>ftst20 test.raf
done

a>dir
A: FTST20   COM : TEST     RAF
a>ftst20 b:test.raf
done

a>dir b:
B: TEST     RAF
a>^D
end of CP/M

CP/M起動後、
save 1 ftst20.com[Enter]
と入力して、FTST20.COMというファイル名でAドライブにセーブしました。
そのあとDIRコマンドを実行して、FTST20.COMがセーブされたことを確認しました。
また、
dir b:[Enter]
と入力して、Bドライブには何も無いことを確認しました。

いよいよテストプログラムの実行です。
まずは
ftst20 test.raf[Enter]
と入力して、AドライブにランダムアクセスファイルTEST.RAFを作成しました。
DIRコマンドでTEST.RAFが作成されたことを確認しました。

次に、
ftst20 b:test.raf[Enter]
と入力して、BドライブにもランダムアクセスファイルTEST.RAFを作成しました。
DIRコマンドでBドライブにもTEST.RAFが作成されたことを確認しました。
このあと、ディレクトリの内容を確認するために、CP/Mを終了してZB3BASICに戻りました。

●ディレクトリ内容の確認

ZB3BASICに戻って、DMコマンドでRAMディスクのディレクトリ内容を確認しました。

参考までに、8300H〜のレコードcfータも表示させました。
そのあと、Aドライブのディレクトリ(アドレス8800H〜)の内容と、Bドライブ(A000H〜)の内容を表示させました。

>dm 8300,830f
8300  26 0F 22 27 29 0E 11 12-16 03 0D FF EB 65 B7 DF  &."')........eキ゚
>dm 8800,883f
8800  00 46 54 53 54 32 30 20-20 43 4F 4D 00 00 00 02  .FTST20  COM....
8810  01 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
8820  00 54 45 53 54 20 20 20-20 52 41 46 00 00 00 2A  .TEST    RAF...*
8830  08 00 00 03 06 07 00 00-04 02 05 00 00 00 00 00  ................
>dm a000,a01f
A000  00 54 45 53 54 20 20 20-20 52 41 46 00 00 00 2A  .TEST    RAF...*
A010  07 00 00 02 05 06 00 00-03 01 04 00 00 00 00 00  ................
>

AドライブのTEST.RAFのFCBは8820H〜883FHです。
BドライブのTEST.RAFのFCBはA000H〜A01FHです。
8830H〜883FH、A010H〜A01FHはブロックbフアローケーションが書かれています。
途中が飛んでいて、b熨O後しています。
この番号と配置の意味については、次回に説明をいたします。

ワンボードマイコンでCP/Mを![第102回]
2012.4.25upload
2012.6.9追記

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