,{c H},{BGCOLOR:dddddd|BOLD|CENTER} ,{c NH},{BGNOCOL|NORMAL} ,{c C},{CENTER} ,{c L},{LEFT} // %第1版第9第刷 // !!!4章 システムコールの使用法  システムコールとは、MSX-DOS の基本的な入出力操作を行う BDOS を、汎用のサブルーチンとしてまとめたもので、あらかじめ決められた手順にしたがってシステムコールを呼び出すことによって MSX のディスクシステムが持つ基本的な機能が簡単に実行できます。  システムコールの役割には、大きく分けると次の 2 つがあります。1 つは、基本的な機能をあらかじめ用意することによってユーザーの負担を少なくすること。もう 1 つは、すべてのプログラムが基本的な機能を共有することによって、移植性や汎用性を高めることです。システムコールを自由自在に活用することによって、プログラムの開発の期間は短縮され、できあがったプログラムは移植性の高いものとなります。  システムコールを実行するには、Z80CPU の C レジスタに決められたファンクション番号を入れ、次のアドレスをコールします。 0005H ……………………………………… MSX-DOS F37DH (&HF37D) ………………………… MSX DISK-BASIC  たとえば、ファンクション番号が 01FH であり、前準備として A レジスタに 00H をセットすることになっているシステムコールがあるとすると、MSX-DOS の場合、このシステムコールは次のようにして呼び出します。 LD A, 00H LD C, 01FH CALL 0005H :  CALL 文の後には、戻り値 (処理の結果) を受け取ったり、退避していたレジスタを復帰させたりする事後処理が続きます。システムコールは DISK-BASIC から利用することもでき、その場合は F37DH 番地がエントリ・アドレスとなります。この場合には、実際は CLEAR 文で確保した領域にマシンコードを格納し、その先頭アドレスを USR 関数で呼び出してやることになります。 '''●システムコールの形式''' 本章では、以下の書式によってシステムコールの使用法を紹介します。 ファンクション : ファンクション番号 設定 : システムコールを行う前にレジスタやメモリ上にセットすべき値 戻り値 : システムコールから戻った時にセットされている値 '''ファンクション:'''  ファンクション番号とは、さまざまなシステムコールの種類を判別するためのもので、それぞれのシステムコールに対応する番号が決められています。システムコールを呼び出すときには、このファンクション番号を C レジスタにセットします。 '''設定:'''  また、システムコールの前準備として、レジスタやメモリに必要な値をセットしなければならないことがありますが、これを本章では "設定:" の部分に示します。 '''戻り値:'''  システムコールの結果得られた値は、多くの場合レジスタやメモリの内容にセットされることになります。これを、本章では出力と呼びますが、この出力がどこに、どのようにセットされているかを "戻り値:" の部分に示します。  ただし、システムコールを使用した後では、この戻り値としてセットされているレジスタやメモリ以外のレジスタの内容が破壊されていることがあります。そこで、システムコールを使用する場合には、そのシステムコールを呼び出す前に、破壊されては困るレジスタの内容を、適当な場所 (スタックなど) に退避させておくようにしてください。  MSX のシステムコールは表 3.11 に示す 42 個ありますが、本章ではこれらを次の 4 つに分類して説明します。 ・周辺機器との I/O ・環境設定 ・アブソリュート READ/WRITE (セクタの直接アクセス) ・FCB を用いたファイルアクセス ,{t},{CENTER} ,{c},{H},{H} ,ファンクション No,機能 ,{c},{C},{L} ,00H,システムリセット ,01H,コンソールから 1 文字入力 (入力待ちあり、エコーバックあり、コントロールコードチェックあり) ,02H,コンソールへ 1 文字出力 ,03H,補助入力装置から 1 文字入力 ,04H,補助出力装置へ 1 文字出力 ,05H,プリンタへ 1 文字出力 ,06H,コンソールから 1 文字入力 (入力待ちなし、エコーバックなし、コントロールコードチェックなし) / 1 文字出力 ,07H,コンソールから 1 文字入力 (入力待ちあり、エコーバックなし、コントロールコードチェックあり) ,08H,コンソールから 1 文字入力 (入力待ちあり、エコーバックなし、コントロールコードチェックあり) ,09H,文字列出力 ,0AH,文字列入力 ,0BH,コンソールからの入力チェック ,0CH,バージョン番号の獲得 ,0DH,ディスクリセット ,0EH,デフォルト・ドライブの選択 ,0FH,ファイルのオープン ,10H,ファイルのクローズ ,11H,ワイルドカードに一致する最初のファイルの検索 ,12H,ワイルドカードに一致する 2 番目以降のファイルの検索 ,13H,ファイルの抹消 ,14H,シーケンシャルなファイルの読み出し ,15H,シーケンシャルなファイルの書き込み ,16H,ファイルの作成 ,17H,ファイル名の変更 ,18H,ログイン・ベクトルの獲得 ,19H,デフォルト・ドライブ名の獲得 ,1AH,DMA アドレスの設定 ,1BH,ディスク情報の獲得 ,1CH〜20H,無効 ,21H,ランダムなファイルの読み出し ,22H,ランダムなファイルの書き込み ,23H,ファイルサイズの獲得 ,24H,ランダムレコード・フィールドの設定 ,25H,無効 ,26H,ランダムブロック書き込み ,27H,ランダムブロック読みだし ,28H,ランダムなファイルの書き込み (不要部を 00H で埋める) ,29H,無効 ,2AH,日付の獲得 ,2BH,日付の設定 ,2CH,時刻の獲得 ,2DH,時刻の設定 ,2EH,ベリファイ・フラグの設定 ,2FH,論理セクタの読み出し ,30H,論理セクタの書き込み {{div_begin style='text-align:center;'}} '''表 3.11 システムコール一覧''' {{div_end}} '''●使用上の注意'''  システムコールのファンクション番号は 00H から 30H までですが、この中には以下に示す 7 個の無効なシステムコールがあります。   '''1CH〜20H, 25H, 29H'''  これらの無効なシステムコールを呼び出した場合には、A レジスタに 00H がセットされる以外は何も行いません。また、ファンクション 31H 以降のシステムコールは未定義であり、使用した場合の結果は不定 (安全性を保証できない) となりますので注意してください。 {{div_begin style='text-align:right;'}} '''リスト 3.3 ユーティリティ・ルーチン''' {{div_end}} ;============================================================ ; ; List 3.3 utility.mac ; ; these routines are used in other programs ; ; GETARG, STOHEX, PUTHEX, PUTCHR, DUMP8B ; ;============================================================ ; PUBLIC GETARG 本プログラムリストに含まれる 5 つのユーティリティ・ル PUBLIC STOHEX ーチンは、後述のサンプルプログラム中で利用される。 PUBLIC PUTHEX PUBLIC PUTCHR PUBLIC DUMP8B BDOS EQU 0005H DMA EQU 0008H ;----- DE := ADDRESS OF ARG(A)'S COPY ----- GETARG: PUSH AF デフォルトの DMA 領域 (0080H〜) に格納されてコマンド PUSH BC ラインの第 n パラメータ (n は A レジスタで指定) とメモ PUSH HL リに取り込み、その先頭アドレスを DE レジスタに返す。 LD C,A LD HL,DMA LD B,(HL) INC HL INC B SKPARG: DEC B JR Z,NOARG SKP1: LD A,(HL) INC HL CALL TRMCHK JR NZ,SKP1 SKP2: LD A,(HL) INC HL CALL TRMCHK JR Z,SKP2 DEC HL DEC C JR NZ,SKPARG CPYARG: LD DE,BUFMEM CPY1: LD A,(HL) LD (DE),A INC HL INC DE CALL TRMCHK JR NZ,CPY1 DEC DE LD A,'$' LD (DE),A LD DE,BUFMEM JR EXIT NOARG: LD DE,BUFMEM LD A,'$' LD (DE),A EXIT: POP HL POP BC POP AF RET TRMCHK: CP 09H RET Z CP 0DH RET Z CP ' ' RET Z CP ';' RET ;----- HL := hexadecimal value of [DE] ----- STOHEX: PUSH AF DE レジスタで指される 16 進文字列を 2 バイト整数に変換 PUSH DE し、HL レジスタに格納する。 LD HL,0000H CALL STOH1 POP DE POP AF RET STOH1: LD A,(DE) INC DE SUB '0' RET C CP 10 JR C,STOH2 SUB 'A'-'0' RET C CP 6 RET NC ADD A,10 STOH2: ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL OR L LD L,A JR STOH1 ;----- print A-reg. in hexadecimal from (00-FF) ----- PUTHEX: PUSH AF A レジスタの内容を 16 進 2 桁で表示する。 RR A RR A RR A RR A CALL PUTHX1 POP AF PUTHX1 PUSH AF AND 0FH CP 10 JR C,PUTHX2 ADD A,'A'-10-'0' PUTHX2: ADD A,'0' CALL PUTCHR POP AF RET ;----- put character ----- PUTCHR: PUSH AF HL レジスタで示すアドレスから 8 バイト文のメモリの内 PUSH BC 容を、16 進およびキャラクターコードでダンプする。 PUSH DE PUSH HL LD E,A LD C,02H CALL BDOS POP HL POP DE POP BC POP AF RET ;----- dumps 8byte of [HL]~[HL+7] in hexa & ascii form ----- DUMP8B: PUSH HL LD B,8 DUMP1: LD A,(HL) INC HL CALL PUTHEX LD A,' ' CALL PUTCHR DJNZ DUMP1 POP HL LD B,8 DUMP2: LD A,(HL) INC HL CP 20H JR C,DUMP3 CP 7FH JR ZN,DUMP4 DUMP3: LD A,'.' DUMP4: CALL PUTCHR DJNZ DUMP2 LD A,0DH CALL PUTCHR LD A,0AH CALL PUTCHR RET ; ----- work area ----- BUFMEM: DS 256 END !!4.1 周辺装置との I/O  入出力に利用するシステムコールであり、コンソール (画面/キーボード) や AUX (外部入出力)、プリンタなどに関する制御を行います。文字列入力やプリンタ出力などのサブルーチンを作成するのは、多くのプログラムに必要なルーチンワークですが、本節のシステムコールを利用することにより、簡単に汎用的なプログラムを組むことができます。 '''●コンソール入力''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:, 01H ,'''設定''' ,:, なし ,'''戻り値''' ,:, A レジスタ ← コンソールから入力した 1 文字  入力がない場合 (キーが押されておらず、入力バッファも空の場合) には、入力待ちを行う。入力された文字はコンソールにエコーバックされる。以下に示すコントロールキャラクタの入力が可能であり、Ctrl-C を受け付けるとプログラムの実行を中断して MSX-DOS のコマンドレベルに戻る。Ctrl-P を受け付けると、以後の入力はすべてプリンタにもエコーバックされるようになり、この状態は、Ctrl-N を受け付けることで解除される。 Ctrl-C システム・リセット Ctrl-P プリンタへのエコー開始 Ctrl-N プリンタへのエコー停止 '''●コンソール出力''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,02H ,'''設定''',:,E レジスタ ← 出力する文字コード ,'''戻り値''',:,なし  E レジスタで指定した文字を画面に表示する。Ctrl-S の入力があると表示動作を停止するが、任意のキーを押すことによって再び表示動作を開始する。 '''●外部入力''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,03H ,'''設定''',:,なし ,'''戻り値''',:,A レジスタ ← AUX デバイスから読み込んだ 1 文字, '''●外部出力''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,04H ,'''設定''',:,E レジスタ ← AUX デバイスに出力するキャラクタコード ,'''戻り値''',:,なし '''●プリンタ出力''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,05H ,''' 設定''',:,E レジスタ ← プリンタに出力するキャラクタコード ,''' 戻り値''',:,なし '''●直接コンソール入出力''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,06H ,''' 設定''',:,E レジスタに 0FFH をセットすれば入力、0FFH 以外をセットすれば出力となる。E レジスタに 0FFH 以外の値がセットされていた場合は、セットされた値をキャラクタコードとみなしてコンソールに出力する。 ,''' 戻り値''',:,E レジスタが 0FFH にセットされていた場合 (入力) には、A レジスタに入力の結果がセットされる。A レジスタにセットされる値は、キーが押されていた場合はそのキャラクターコード、押されていなかった場合は 00H となる。E レジスタが 0FFH 以外にセットされていた場合 (出力) には、戻り値はなし。  コントロールキャラクタのサポート、入力のエコーバックは行わない。 '''●直接コンソール入力 その 1''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,07H ,''' 設定''',:,なし ,''' 戻り値''',:,A レジスタ ← コンソールから入力した 1 文字  コントロールキャラクタのサポートは行わない。エコーバックは行わない。 '''●直接コンソール入力 その 2''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,08H ,''' 設定''',:,なし ,''' 戻り値''',:,A レジスタ ← コンソールから入力した 1 文字  エコーバックは行わない。コントロールキャラクタはファンクション 01H と同様に処理する。 '''●文字列出力''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,09H ,''' 設定''',:,DE レジスタ ← メモリ上に用意した、コンソールに出力すべき文字列の先頭アドレス ,''' 戻り値''',:,なし  文字列の最後には、終端記号として 24H ("$") を付加しておく必要がある。ファンクション 02H (コンソール出力) と同様に CTRL-S を処理する。 '''●文字列入力''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,0AH ,''' 設定''',:,最大入力文字数 (1〜0FFH) をセットしたメモリのアドレスを、DE レジスタにセットする。 ,''' 戻り値''',:,DE レジスタに示されたアドレスに 1 を加えたアドレスにはコンソールから実際に入力された文字数を、DE レジスタに示されたアドレスに 2 を加えたアドレス以降には、コンソールから入力された文字列をセットする。  リターンキーの入力をコンソールからの入力の終端とみなす。ただし、入力文字数が指定の文字数 (DE レジスタで示されるアドレスの内容 = 1〜255) を越える場合には、指定の入力文字数までを入力文字列とみなしてメモリにセットした後、処理を終了する。次の文字からリターンキーまでの入力は無視される。このシステムコールによる文字列入力時には、テンプレートによる編集が可能である。 '''●コンソールの状態チェック''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,0BH ,''' 設定''',:,なし ,''' 戻り値''',:,キーボードが押されていた場合には 00H を、押されていなかった場合には 0FFH を、A レジスタにセットする。 !!4.2 環境の設定と読み出し  デフォルト・ドライブの変更やシステムのさまざまなデフォルト値のセットなど、MSX システムの環境設定を行うためのシステムコールです。 '''●システム・リセット''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,00H ,''' 設定''',:,なし ,''' 戻り値''',:,なし  MSX-DOS 上からコールした場合には、0000H に分岐することによってシステムがリセットされる。MSX DISK-BASIC 上からコールした場合には、MSX DISK-BASIC がウォームスタート (Warm Start) する。つまり、ロードされているプログラムを破壊せずに BASIC のコマンドレベルに戻る。 '''●バージョン番号の獲得''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,0CH ,''' 設定''',:,なし ,''' 戻り値''',:,HL レジスタ ← 0022H  このシステムコールは、CP/M における、さまざまな CP/M のバージョン番号を獲得するためのものであるが、MSX-DOS の場合には、一律に 0022H がセットされる。 '''●ディスクリセット''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,0DH ,''' 設定''',:,なし ,''' 戻り値''',:,なし  変更されたがまだディスクに書き込まれていないセクタがあれば、それをディスクに書き込んだ後、デフォルト・ドライブを A ドライブにセットし、DMA を 0080H にセットする。 '''●デフォルト・ドライブの変更''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,0EH ,''' 設定''',:,"E レジスタ ← デフォルト・ドライブ番号 (A=00H, B=01H, …)" ,''' 戻り値''',:,なし  システムコールによるディスクアクセスは、特に指定しない限りデフォルト・ドライブ番号で示されるデフォルト・ドライブに対して行われる。ただし、システムコールを呼び出す際に指定された FCB にセットされているドライブ番号が 00H 以外であった場合には、本システムコールによってセットされているデフォルト・ドライブの設定は無視される。 '''●ログイン・ベクトルの獲得''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,18H ,''' 設定''',:,なし ,''' 戻り値''',:,HL レジスタ ← オンライン・ドライブ情報  オンライン・ドライブとは、MSX に正常な状態で接続され、かつその電源が投入されているドライブを指す。このシステムコールを実行すると各ドライブがオンラインであるか否かを調べ、その結果を図 3.22 のように HL レジスタに入れて返す。それぞれのビットが "1" ならば対応するドライブはオンラインであり、"0" ならばそうでないことを示す。 ,{c CS},{CENTER|SIZE:30} ,{c},{CENTER|SIZE:200},{CS},{CS},{CS},{CS},{CS},{CS},{CS},{CS},{CS},{CS},{CS},{CS},{CS},{CS},{CS},{CS} ,'''レジスタ名''','''H'''{COLS:8},,,,,,,,'''L'''{COLS:8} , ビット番号, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0 , ドライブ名, MSX-DOS では意味を持たない{COLS:8},,,,,,,,H:, G:, F:, E:, D:, C:, B:, A: , オンライン/オフライン,各ビットについて、オンなら 1 が、オフなら 0 がセットされる。{COLS:16} {{div_begin style='text-align:center;'}} '''図3.22 ログイン・ベクトル''' {{div_end}} '''●デフォルト・ドライブ番号の獲得''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,19H ,''' 設定''',:,なし ,''' 戻り値''',:,"A レジスタ ← デフォルト・ドライブ番号 (A=00H, B=01H, …)" '''●転送先アドレスの設定''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,1AH ,''' 設定''',:,DE レジスタ ← 設定する転送先アドレス (DMA アドレス) ,''' 戻り値''',:,なし  DMA アドレスは、システムリセット時に 0080H に初期化されるが、このファンクション 1AH のシステムコールを用いることによって、任意のアドレスに設定し直すことができる。 '''●ディスク情報の獲得''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,1BH ,''' 設定''',:,E レジスタ ← 目的のディスクが入っているドライブ番号 , , ,"(デフォルト・ドライブ=00H, A=01H, B=02H,…)" ,''' 戻り値''',:,A レジスタ ← 1 クラスタあたりの論理セクタ数 , , ,(E レジスタの設定が不適当だった場合 FFH) , , ,BC レジスタ ← 論理セクタのサイズ , , ,DE レジスタ ← クラスタの総数 , , ,HL レジスタ ← 未使用クラスタの総数 , , ,IX レジスタ ← DPB の先頭アドレス , , ,IY レジスタ ← メモリ上の FAT の先頭アドレス  指定ドライブのディスクの情報を得るシステムコールである。ドライブ番号に 00H を指定するとデフォルト・ドライブの指定になる。それ以外は、A ドライブなら 01H、B ドライブなら 02H、…を指定する。  このシステムコールは MSX-DOS 用に変更されたもので、CP/M との互換性はない。 '''●日付の獲得''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,2AH ,''' 設定''',:,なし ,''' 戻り値''',:,HL レジスタ ← 年 , ,,D レジスタ ← 月 , ,,E レジスタ ← 日 , ,,A レジスタ ← 曜日  このシステムコールは MSX-DOS 用に増設されたもので、CP/M との互換性はない。 '''●日付の設定''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,2BH ,''' 設定''',:,HL レジスタ ← 年 , ,,D レジスタ ← 月 , ,,E レジスタ ← 日 ,''' 戻り値''',:,設定が成功したかどうかを A レジスタにセットする。成功なら 00H が、失敗なら 0FFH がセットされる。  このシステムコールは MSX-DOS 用に増設されたもので、CP/M との互換性はない。 '''●時刻の獲得''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,2CH ,''' 設定''',:,なし ,''' 戻り値''',:,H レジスタ ← 年 , ,,L レジスタ ← 分 , ,,D レジスタ ← 秒 , ,,E レジスタ ← 1/100 秒  このシステムコールは MSX-DOS 用に増設されたもので、CP/M との互換性はない。 '''●時刻の設定''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,2DH ,''' 設定''',:,H レジスタ ← 年 , ,,L レジスタ ← 分 , ,,D レジスタ ← 秒 , ,,E レジスタ ← 1/100 秒 ,''' 戻り値''',:,成功なら 00H が、失敗なら 0FFH が A レジスタにセットされる。  このシステムコールは MSX-DOS 用に増設されたもので、CP/M との互換性はない。 '''●ベリファイ・フラグの設定''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,2EH ,''' 設定''',:,ベリファイ・フラグをリセットする時には、E レジスタ ← 00H , ,,ベリファイ・フラグをセットする時には、E レジスタ ← 00H 以外の値 ,''' 戻り値''',:,なし  ベリファイ・フラグを設定すると、以後のディスクに対する書き込みがベリファイ付きで行われるようになる。つまり、書き込んだ後でその内容をディスクから読み出して、書き込むべき内容と比較して等しいかどうかをチェックする。  このシステムコールは MSX-DOS 用に増設されたもので、CP/M との互換性はない。 !!4.3 アブソリュート READ/WRITE (セクタの直接アクセス)  MSX では、"論理セクタ" と呼ばれるものを最小の単位としてディスクを管理しています。論理セクタとは、ディスクの物理的なセクタと無関係に定められたセクタであり、第 0 論理セクタから最大論理セクタ (ディスクの種類によってその数は異なる) までの一連の番号が付けられています。  この論理セクタのおかげで、MSX-DOS や MSX DISK-BASIC のユーザーは、ディスクのメディアタイプによって異なる 1 トラックごとの物理セクタ数の違いを考慮せずにディスクをアクセスすることが可能となっています。実際には FCB (ファイル・コントロール・ブロック) を介するシステムコールを用いることで、論理セクタさえも意識しない手軽でキメ細かなファイルの取り扱いができますから、この論理セクタを実際に使用する必要はありません。しかし、論理セクタを用いたアクセスも用途によっては必要であり、MSX-DOS および MSX DISK-BASIC では、論理セクタのアクセスするシステムコールも用意しています。  本節では、この論理セクタのアクセスを行うシステムコールを説明します。 '''●論理セクタを用いた読み出し''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,2FH ,'''  設定''',:,"読み出しを開始する論理セクタの番号 (複数の場合はその先頭の論理セクタ番号) を DE レジスタにセットする。読み出す論理セクタの個数を H レジスタに、読み出すディスクのドライブ番号 (A=00H, B=01H, …) を L レジスタにセットする。" ,''' 戻り値''',:,読み込んだ内容を DMA バッファにセットする。  指定ドライブの指定論理セクタから、指定された個数の (連続した) 論理セクタを読み出し、その内容を DMA 以降のメモリに格納する。その際、格納されるメモリ領域は、ファンクション 1AH (転送先アドレスの設定) によって十分な量 (読み出す論理セクタの個数×論理セクタのサイズバイト以上) を確保しておく必要がある。  このシステムコールは MSX-DOS 用に増設されたもので、CP/M との互換性はない。 '''●論理セクタを用いた書き込み''' ,{t},{BSIZE:0} ,{c},{BSIZE:0|RIGHT|TOP|SIZE:130},{BSIZE:0|TOP},{BSIZE:0} ,'''ファンクション''',:,30H ,''' 設定''',:,"書き込む内容を DMA で示されるアドレス以降のメモリ領域にセットする。書き込みを始める論理セクタの番号を、DE レジスタにセットする。書き込む論理セクタの個数を H レジスタにセットする。書き込むドライブ番号 (A=00H, B=01H, …) を L レジスタにセットする。" ,''' 戻り値''',:,なし  このシステムコールは MSX-DOS 用に増設されたもので、CP/M との互換性はない。 {{div_begin style='text-align:right;'}} '''リスト 3.4 クラスタ・ダンプ''' {{div_end}} ;============================================================ ; ; List 3.4 cluster dump ; ; this program must link List 3.3 ; ;============================================================ ; EXTRN GETARG コマンドラインで指定した任意のクラスタの先頭の 128 バイトをダンプする。 EXTRN STOHEX EXTRN PUTHEX EXTRN PUTCHR EXTRN DUMP8B BDOS EQU 0005H ;----- program start ----- LD A,1 CALL GETARG ;[DE] := 1st argument of commnad line CALL STOHEX ;HL := evaluate [DE] as hexadecimal ; this is target cluster No. PUSH HL LD E,00H ;request the default drive LD C,1BH ;get disk information CALL BDOS POP HL CP 0FFH ;fail ? JR NZ,L2 ;if not fail, A := sector/cluster and goto L2 LD DE,ERMSG1 ;[DE] := 'Cannot get Disk information' LD C,09H ;string output function CALL BDOS RET ;error return L2: LD E,(IX+12) ;DE := 1st sector of data area LD E,(IX+13) DEC HL DEC HL ;HL := cluster Np. -2 LD B,H LD C.L ;BC := cluster No. -2 LOOP: DEC A ;Count N times JR Z,RESULT ADD HL,BC JR LOOP RESULT: ADD HL,DE ;HL := sector of target cluster PUSH HL ;save target sector LD DE,NEWDMA ;we reserved 1024 bytes area for DMA LD C,1AH ;set DMA address function CALL BDOS LD C,19H CALL BDOS ;default drive? LD L,A POP DE ;DE := target sector LD H,1 ;H := 1 (read 1 secter onlu) LD C,2FH ;abusolute read function CALL BDOS ;data will be set into DMA DUMP: LD HL,NEWDMA ;HL := DMA address LD DE,0000H ;DE := relative address from cluster top LD B,16 ;dump 16 lines DLOOP: PUSH BC LD A,D CALL PUTHEX LD A,E CALL PUTHEX LD A,' ' CALL PUTCHR PUSH HL LD HL,8 ADD HL,DE EX DE,HL ;DE := DE+8 POP HL CALL DUMP8B ;8 bytes dump subroutin (in another file) POP BC DJNZ DLOOP ;all work habe done. RET ;----- work area ----- NEWDMA: DS 1024 ;Private DMA area ADRS: DS 2 ERMSG1: DB 'Cannot get Disk information.$' ERMSG2: DB 'Cannot read that cluster.$' END !!4.4 FCB を用いたファイルアクセス  前節で述べた論理セクタを直接読み書きをするタイプのシステムコールでは、ファイル単位のアクセスが非常に困難であり、ファイルを基本としたディスクアクセスを行うためには、FCB を介するシステムコールを使用する必要があります。  FCB を用いるシステムコールには、大きく分けて次の 3 つの種類が存在します。1 つはシーケンシャル・ファイルアクセスであり、もう 1 つはランダム・ファイルアクセスです。この 2 つは CP/M との互換性を保つために用意されたシステムコールであり、MSX-DOS が持っている力を十分に引き出すものとはいえません。それに対して、3 つ目のランダム・ブロック・アクセスは MSX システムの独自のシステムコールになっています。このランダム・ブロック・アクセスは、次のような特徴を持っています。 ・レコードサイズを任意に設定できる ・複数のレコードをランダムにアクセスできる ・ファイルの大きさをバイト単位で管理できる  本節では、このランダム・ブロック・アクセスを含む、FCB を利用したファイルアクセスのためのシステムコールを説明します。  (FCBが4000Hから7FFFHまでにあると、*の処理と、デバイス(CON,PRN,NUL,AUX)に対する入出力が正しくできない) '''●ファイルのオープン''' ファンクション : 0FH 設定 : DE レジスタ ← オープンされていない FCB の先頭アドレス 戻り値 : ファイルのオープンが成功すれば 00H を、失敗すれば 0FFH を A レジスタにセットする。ファイルのオープンが成功した場合には、指定された FCB の各フィールドの設定が行われる。  ドライブ番号に 00H をセットすると、ファンクション 0EH (デフォルト・ドライブの設定) によって設定されているデフォルト・ドライブによる指定が有効になる。デフォルト・ドライブ以外のファイルをオープンする場合には、A ドライブなら 01H、B ドライブなら 02H、…のように指定する。  このシステムコールを利用してファイルをオープンすると、ディスク上のディレクトリ領域の情報から、レコードサイズ、カレントブロック、カレントレコード、ランダムレコードの各フィールドを除く、すべての FCBのフィールドが設定される。設定されてないフィールドについては、本システムコール実行後にユーザーが必要に応じて設定する必要がある。FCBの各フィールドがセットされたこの状態が、FCBを介するシステムコールを利用するユーザーにとって真に "ファイルがオープンされた状態" であり、以下に説明する、FCBを用いたファイルアクセスを行うシステムコールが利用できるようになる。 '''●ファイルのクローズ''' ファンクション : 10H 設定 : DE レジスタ ← オープンされた FCB の先頭アドレス 戻り値 : ファイルのクローズが成功すれば 00H を、失敗すれば 0FFH を A レジスタにセットする。さらに FCB のドライブ番号を設定する。  現在のメモリ上の FCB の内容をディスク上の該当するディレクトリ・エリアに書き込むことによって、ファイルの更新に関する整合性を保つ。ファイルに対して読み込みしか行っていない場合には、このシステムコールを使ってファイルをクローズする必要はない。 '''●ファイルの検索 その 1''' * ファンクション : 11H 設定 : DE レジスタ ← オープンされていない FCB の先頭アドレス 戻り値 : ファイルが見つかった場合には 00H を、見つからなかった場合は 0FFH を A レジスタにセットする。見つかった場合にはさらに、DMA で示される領域にそのファイルのディスク上のディレクトリ・エントリ (32 バイト) をセットする。また FCB のドライブ番号もセットする。  ファイル名にはワイルドカード・キャラクタを使用することができる。たとえば、ワイルドカード・キャラクタを使って "????????.c" という指定を行うと、「先頭の文字列はなんてもよいが、末尾に ".c" が付くファイル名」を検索し、最初にマッチしたファイルのディレクトリ情報を DMA 以降に書き込む。マッチするすべてのファイルを検索したい場合や、マッチするファイルが 1 個だけかどうかを知りたい場合には、次に紹介するファンクション 12H を利用する必要がある。 '''●ファイルの検索 その 2''' * ファンクション : 12H 設定 : なし 戻り値 : 見つかった場合には 00H を、見つからなかった場合には 0FFH を A レジスタにセットする。見つかった場合にはさらに、DMA で示される領域にそのファイルのディレクトリ・エントリ (32 バイト) をセットする。さらに、FCBドライブ番号を設定する。  このシステムコールは、ファンクション 11H のワイルドカード・キャラクタによるファイル名の指定とマッチした複数のファイルを検索する時に使用するもので単独で使用しても意味がない。  このシステムコールを使用すると、ファンクション 11H によってマッチした複数のファイルのディレクトリ情報を、1 つずつ順番に得ていくことができる。 '''●ファイルの抹消''' ファンクション : 13H 設定 : DE レジスタ ← オープンされた FCB の先頭アドレス 戻り値 : 抹消が成功した場合には 00H を、失敗した場合には 0FFH を A レジスタにセットする  ファイル名にワイルドカード・キャラクタを使用して、複数のファイルを一度に抹消することができる。 '''●シーケンシャルな読み出し''' ファンクション : 14H 設定 : DE レジスタ ← オープンされた FCB の先頭アドレス FCB のカレントブロック ← 読み出しを開始するブロック FCB のカレントレコード ← 読み出しを開始するレコード 戻り値 : 読み込みが成功すれば 00H を、失敗すれば 01H を A レジスタにセットする。成功した場合には、読み込んだ 1 レコードを DMA で示される領域にセットする  FCB のカレントブロックとカレントレコードは、読み込み後に自動的に更新される。つまり、連続して読み込む場合には、カレントブロックとカレントレコードをセットする必要はない。読み込むレコードサイズは 128 バイト固定。 '''●シーケンシャルな書き込み''' ファンクション : 15H 設定 : DE レジスタ ← オープンされた FCB の先頭アドレス FCB のカレントブロック ← 書き込みを開始するブロック FCB のカレントレコード ← 書き込みを開始するレコード DMA 以降の 128 バイト ← 書き込むデータ 戻り値 : 書き込みが成功すれば 00H を、失敗すれば 01H を A レジスタにセットする。  FCB のカレントブロックとカレントレコードは、書き込み後に自動的に更新される。 '''●ファイルの作成''' ファンクション : 16H 設定 : DE レジスタ ← オープンされていない FCB の先頭アドレス 戻り値 : ファイルの作成が成功すれば 00H を、失敗すれば 0FFH を A レジスタにセットする  FCB 中のレコードサイズ、カレントブロック、カレントレコード、ランダムレコードの各フィールドについては、これらを本システムコールの実行後に必要に応じてセットしておく必要がある。 '''●ファイル名の変更''' ファンクション : 17H 設定 : 旧ファイル名に対応する FCB の 18 バイト目 (FCB のファイルサイズ・フィールドの 2 バイト目=旧ファイル名の 16 バイト後方) からの 11 バイトに (18〜28 バイト) 新ファイル名をセットし、その FCB アドレスを DE レジスタにセットする 戻り値 : ファイル名の変更が成功すれば 00H を、失敗すれば 0FFH を A レジスタにセットする  新旧ファイル名に、ワイルドカード・キャラクタ "?" を使用できる。たとえば、旧ファイル名に "????????.o" を、新ファイル名に "????????.obj" を指定すれば、".o" という拡張子を持つすべてのファイルについて、拡張子を ".obj" に変更することができる。 '''●ランダムな読み出し''' ファンクション : 21H 設定 : DE レジスタ ← オープンされた FCB のアドレス FCB のランダムレコード ← 読み出すレコード 戻り値 : 読み込みが成功すれば 00H を、失敗すれば 01H を A レジスタにセットする。読み込みが成功した場合には、DMA で示される領域に読み込んだ 1 レコードの内容をセットする レコードの大きさは 128 バイト固定長。 '''●ランダムな書き込み''' ファンクション : 22H 設定 : DE レジスタ ← オープンされた FCB の先頭アドレス FCB のランダムレコード ← 書き込むレコード DMA 以降の 128 バイト ← 書き込むデータ 戻り値 : 書き込みが成功すれば 00H を、失敗すれば 01H を A レジスタにセットする レコードの大きさは 128 バイト固定長。 '''●ファイルサイズの獲得''' ファンクション : 23H 設定 : DE レジスタ ← オープンされた FCB の先頭アドレス 戻り値 : ファイルサイズの獲得が成功すれば 00H を、失敗すれば 0FFH を A レジスタにセットする。獲得が成功すれば、FCB のランダムレコード・フィールドに、指定されたファイルの 128 バイト単位のサイズをセットする。 ファイルのサイズは 128 バイト単位で計算されます。つまり、200 バイトであれば 2 が、257 バイトであれば 3 がセットされます。 '''●ランダムレコード・フィールドの設定''' ファンクション : 24H 設定 : DE レジスタ ← オープンされた FCB の先頭アドレス FCB のカレントブロック ← 目的のブロック FCB のカレントレコード ← 目的のレコード 戻り値 : ランダムレコード・フィールドに、指定された FCB のカレントブロック・フィールドとカレントレコード・フィールドから計算したカレントレコード・ポジションをセットする。 '''●ランダムな書き込み その 2''' ファンクション : 26H 設定 : DE レジスタ ← オープンされた FCB の先頭アドレス FCB のレコードサイズ ← 書き込むレコードサイズ FCB のランダムレコード ← 書き込みを開始するレコード HL ← 書き込むレコード数 DMA 以降のメモリ領域 ← 書き込むデータ 戻り値 : データの書き込みに成功すれば 00H、失敗すれば 01H を A レジスタにセットする  書き込みが終わると、ランダムレコード・フィールドの値が自動的に更新されて、最後に書き込んだレコードの次のレコードを指す。ひとつのレコードの大きさは FCB のレコードサイズ・フィールドによって 1 バイトから 65535 バイトまで任意に設定できる。  このシステムコールは MSX-DOS 用に増設されたもので、CP/M との互換性はない。 '''●ランダムな読み出し その 2 (ランダム・ブロック・アクセス)''' ファンクション : 27H 設定 : DE レジスタ ← オープンされた FCB の先頭アドレス FCB のレコードサイズ ← 読み出すレコードサイズ FCB のランダムレコード ← 読み出しを開始するレコード HL ← 読み出すレコード数 戻り値 : データの読み出しに成功すれば 00H、失敗すれば 01H を A レジスタにセットする。さらに HL レジスタに、実際に読み込んだレコードの個数をセットする。  読み込みが終わると、ランダムレコード・フィールドの値が自動的に更新される。このシステムコール実行後、HL レジスタには実際に読み込んだレコードの総数がセットされる。つまり、指定した数のレコードを読み終わる前にファイルの終わりに達した場合には、それまでに読み込んだ実際のレコード数が HL レジスタに入ることになる。  このシステムコールは MSX-DOS 用に増設されたもので、CP/M との互換性はない。 '''●ランダムな書き込み その 3''' ファンクション : 28H 設定 : DE レジスタ ← オープンされた FCB の先頭アドレス FCB のランダムレコード ← 書き込むレコード DMA 以降の 128 バイト ← 書き込むデータ 戻り値 : 書き込みが成功すれば 00H を、失敗すれば 01H を A レジスタにセットします。  レコードの大きさは 128 バイト固定長。  本システムコールでは、書き込みによってファイルが大きくなる場合、追加されたレコードを 00H で埋めて、指定されたレコードに書き込みを行う。この点を除けばファンクション 22H (ランダムな書き込み) と同じである。  ファンクション22Hでもファイルが大きくなる場合、領域が確保されるが、その内容はゴミです。 {{div_begin style='text-align:right;'}} '''リスト 3.5 ファイル・ダンプ''' {{div_end}} ;============================================================ ; ; List 3.5 file dump ; ; this program must link List 3.3 ; ;============================================================ ; EXTRN GETARG コマンドラインで指定した任意ファイルをダンプする。 EXTRN STOHEX EXTRN PUTCHR EXTRN PUTHEX EXTRN DUMP8B BDOS EQU 0005H コマンドラインの第 1 パラメータとして指定したファイル名は、デフォルト FCB エリア (005CH〜) に格納される。 FCB EQU 005CH ;----- program start ----- LD DE,FCB ;DE := default FCB address LD C,0FH ;open file function CALL BDOS OR A ;success ? JR Z,READ if so, goto READ LD DE,ERMSG1 ;[DE] := 'Cannot open that file' LD C,09H ;string output function CALL BDOS RET ;error return READ: LD A,2 CALL GETARG ;get 2nd argument of command line CALL STOHEX ;HL := value of the argument LD (ADRS),HL ;set address counter LD DE,NEWDMA LD C,1AH ;set DMA address function CALL BDOS LD HL,8 LD (FCB+14),HL ;record size := 8 LD HL,0 LD (FCB+33),HL LD (FCB+35),HL ;random record := 0 RD1: LD HL,NEWDMA ;clear DMA area LD B,8 RD2: LD (HL),' ' INC HL DJNZ RD2 LD HL,1 ;read 1 record LD DE,FCB LD C,27H ;random block read function CALL BDOS OR A ;success ? JR Z,DUMP ;if so, goto DUMP LD DE,ERMSG2 ;[DE] := 'Ok.' LD C,09H ;string output function CALL BDOS RET DUMP: LD HL,(ADRS) LD A,H CALL PUTHEX LD A,L CALL PUTHEX LD A,' ' CALL PUTCHR LD DE,8 ADD HL,DE LD (ADRS),HL LD HL,NEWDMA CALL DUMP8B ;dump 8 byte JR RD1 ;----- work area ----- ADRS: DS 2 NEWDMA: DS 8 ;----- error message ----- ERMSG1: DB 'Cannot open that file.$' ERMSG2: DB 'Ok.$' END