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

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

[第15回]

●CP/Mのファイルはページ単位で保存される

前回説明をしましたように、CP/MではプログラムやデータをSAVEするときに、メモリ上の実際のバイト数ではなくて、ページという単位でそれを行ないます。
1ページは256バイトです。

たとえばメモリ上のプログラムが300バイトの長さでも、400バイトでもあるいは500バイトでも、それをファイルとして保存するときは、2ページ512バイトのプログラム(データ)として保存してしまいます。
当然、そのファイルをディスクからメモリに読み出すときも、そのサイズ(ページ単位)の通りにメモリに書き出します。

つまり、ディスクにファイルとして保存されたプログラムやデータは本来の長さの後ろに余計な部分がくっついていることになります。
プログラムの場合には、いくら後に余計なものがくっついていたとしても、プログラム以外の部分はどうせ参照されることはありませんから、特に支障はありません。
しかしそれがテキストファイルの場合には、ちょっと困ったことになってしまいます。

●テキストファイルの中味を表示するプログラム

CP/Mシステムの中核はBDOSですが、そのさらに中心とでも言うべき機能にファンクションコール(システムコールとも言うようです)があります。
Cレジスタに機能を選択するための番号を入れてアドレスの0005HをCALLすることで、文字列の表示やファイルのオープンやREAD、WRITEなど、いろいろな処理を行なうことができます。

先日から、ND80ZVに仮に移植したCP/M2.2の動作テストを行なうために、このファンクションコールを使ったテストプログラムを書いて、それを実行することで、動作の確認をしています。

Y様から送っていただいた3冊のCP/M解説書([第2回]参照)のうちの「応用CP/M」には、このファンクションコールを使ったサンプルプログラムがたくさんついています。
そのリストの通りのプログラムを書いて、それを実行して、そこに書いてある通りの結果が得られれば、ND80ZVへの移植は成功したと評価できることになります。

そこで、先日から、その「応用CP/M」に書かれているサンプルプログラムを順に入力し、それを実行しては結果を確認する、という作業を行なっています。
そのサンプルプログラムは8080のニーモニックで書かれていますが、私はZ80ニーモニックに慣れてしまっていますから、そのリストを見ながらZ80ニーモニックに直してプログラムを書いています。

そのサンプルプログラムの中に、ディスクに保存されているテキストファイルの中味を表示する、というプログラムがあります。
MSDOSのTYPEコマンドと同じ機能のプログラムです。

CP/MにもTYPEコマンドがあります(本当はCP/Mが元祖でMSDOSはその真似をしたのですけれど)。
TYPEコマンドは、CCP(Console Command Processor)のコマンドです。
TYPEコマンドもそれ以外のコマンドも、BDOSに用意されている機能(ファンクションコール)を使って組み立てられています。

ということは、ファンクションコールを使えば、TYPEコマンドと同じ機能のプログラムを書くことができる、ということになります。

下は「応用CP/M」の82ページに書かれている、TYPEコマンドと同じ働きをするサンプルプログラムをZ80ニーモニックに書き直したものです。
前にも書いたことですが、本に書かれているプログラムを、8080ニーモニックからZ80ニーモニックに書き直しても、それは翻訳と同じことですから、そのまま公開するわけにはいきません。
そこで一部のみをお見せすることにいたします。

2012/1/16  17:49  T1520.TXT
END=814A
              ; cp/m t1520 オウヨウcp/m p.82
              ;12/1/16
              ;
                ORG $8100
                FCB=$805C
                FCBCR=$807C
                DMABF=$8080
                DIRPOINT=$8790
                BDOS=$C409
              ;
8100 0E0F     START:LD C,0F;=15
8102 115C80     LD DE,FCB
8105 CD09C4     CALL BDOS
8108 FEFF       CP FF
810A CA3181     JP Z,OPNERR


8131 0E09     OPNERR:LD C,09
8133 113A81     LD DE,MSGERR
8136 CD09C4     CALL BDOS
8139 C9         RET
813A 0D       MSGERR:DB 0D
813B 0A         DB 0A
813C 0A         DB 0A
813D 46494C45   "FILE"
8141 20474120   " GA "
8145 4E4149     "NAI"
8148 0D         DB 0D
8149 0A         DB 0A
814A 24         "$"
              ;END
              
BDOS         =C409  DIRPOINT     =8790  DMABF        =8080  
FCB          =805C  FCBCR        =807C  MSGERR       =813A  
NXTREC       =8111  OPNERR       =8131  SCROUT       =811F  
START        =8100  

上のリスト中でCALL BDOS(CD09C4)と書いてあるCALL命令がファンクションコールです。
CP/Mのファンクションコールは、本当はアドレス5番地をコールするのですが、今はまだCP/Mの動作テスト中なので、ダイレクトにBDOS内のアドレスをCALLしています。

上のリストにあるように、Cレジスタにファンクションナンバーを入れ、必要ならDEレジスタにパラメータを入れた上で、BDOSをコールします。
このリストでは、ファンクション0F(=15)、09の各ファンクションをコールしているところが見えています。
参考までに、各ファンクションコールの機能は次の通りです。

[ファンクション09]文字列を表示する
DEレジスタで指定するアドレスから$マーク(24H)までの文字列をコンソールに表示します。
[ファンクション0F]ファイルオープン
DEレジスタで指定するアドレスに書かれているファイル名をデイレクトリからみつけて、そのファイルをオープンします。

●プログラムを実行する

さて、このプログラムを実行して、その結果を確認してみることにします。
このプログラムのソースプログラムをt1520.txtというファイル名で仮想フロッピーディスクにSAVEしておきます。
そして、
t1520 t1520.txt[Enter]
を実行します。
その結果、出力されたのが下のリストです(途中は一部省略してあります)。

a>t1520 t1520.txt
; cp/m t1520 オウヨウcp/m p.82
;12/1/16
;
        ORG $8100
        FCB=$805C
        FCBCR=$807C
        DMABF=$8080
        DIRPOINT=$8790
        BDOS=$C409
;
START:LD C,0F;=15
        LD DE,FCB
        CALL BDOS
        CP FF
        JP Z,OPNERR
        XOR A

        " GA "
        "NAI"
        DB 0D
        DB 0A
        "$"
;END

+ケPl!・кKンョ莎ソョ玩ノタ。<Uュ\"hー楳Dシ?ヨG鹿エwソヤス淌s「@ネDDー"NQ-?互轗oヒ]ソ脹+XSム"MAH%ソメyマク齢Bノケtチ「…5機A!源Dヲレ{_bZUcoニ」A ィDワ, B D√マlェ゚D゚/=>ロタ`タ,D1L
,bKォヒ[}セnレx釈yル鴆%輊 (t

ご覧の通り、リストの終わりのさらに後に「ゴミ」がいっぱい表示されてしまいました。
今回の最初のところで書きましたように、CP/Mはページ単位でファイルセーブを行なうために、プログラムやデータの正確なサイズが保存されません。
ファイルの中味をページ単位で表示すると、上のように、余計なゴミまで表示されてしまうことになります。

それでは、TYPEコマンドではどうなるか?
と思って試してみましたら、やっぱり同じ結果になってしまいました。

●EOF(End Of File)

実はCP/Mでは、このような結果になるのを避けるために、テキストファイルの場合には、ファイルの最後にEOF(End Of File)コードをつけることになっていたようです。
EOFコードは1Aです。
MSDOSではファイルは正確なファイルサイズ(バイト数単位)の情報とともに保存しますから、テキストファイルでもEOFコードは使いません。
前回説明しましたように、ND80ZVのZB3BASICでも、それは同じです。

どうもそういうことらしい、ということがわかりましたから、ファイルの終わりにEOFを追加してみることにしました。

●ZB3BASICシステムが威力を発揮します

こういうときにND80ZVのZB3BASICシステムは威力を発揮します。
CP/Mを一旦終了して、ND3BASICに戻ります。
CP/Mを終了するには、[Ctrl]+[C]を入力するのが本来なのですが、そうするとZB3BASICも終了してしまいますから、ここでは仮に[Ctrl]+[D]を使うように、CP/Mを書き換えてあります。
CP/MからZB3BASICに戻るときにエラーが表示されているのは、もともとのZB3BASICが、こういう使い方を想定していないためです。
エラーが表示されても、特に支障はありません。

,bKォヒ[}セnレx釈yル鴆%輊 (t
a>^D

ERR:23
>/ld t1520.txt,8100
loading T1520.TXT ...0218(536)bytes loaded,from 8100 to 8317 
>d.,8300,837f
8300  0D 0A 09 44 42 20 30 41-0D 0A 09 22 24 22 0D 0A  ...DB 0A..."$"..
8310  3B 45 4E 44 0D 0A 0D 0A-2B 00 B9 50 6C 01 21 10  ;END....+.ケPl.!.
8320  A5 F9 ED 84 7B 4B DD AE-E4 B3 BF AE 8A DF C9 94  ・...{Kンョ.ウソョ.゚ノ.
8330  1C C0 A1 3C 1A 55 AD 5C-22 08 68 00 B0 94 80 44  .タ。<.Uュ\".h.ー..D
8340  BC 3F D6 47 8E AD B4 77-F1 FB BF D4 BD 9F C3 73  シ?ヨG.ュエw..ソヤス.テs
8350  A2 14 40 C8 03 44 00 44-B0 05 01 18 22 4E 51 08  「.@ネ.D.Dー..."NQ.
8360  2D F9 3F FF 8C DD F9 E7-7D 6F CB 5D BF 92 AF F5  -.?..ン..}oヒ]ソ.ッ.
8370  2B 00 80 14 58 53 07 D1-22 4D 41 48 00 00 25 04  +...XS.ム"MAH..%.
>cm 8318
8318 2B-1a
8319 00-
>d.,8310,831f
8310  3B 45 4E 44 0D 0A 0D 0A-1A 00 B9 50 6C 01 21 10  ;END......ケPl.!.
>jp bc00

a>save 3 t1520.txt
a>


t1520.txtは仮想フロッピーディスクに保存してあるだけではなくて、Windowsのハードディスクにも保存してあります。
ZB3BASICの/LDコマンドでそれをメモリーにロードします。
そのあとDMコマンド(Dump Memory。ここでは省略形のD.を使っています)でテキストファイルの終わり近くを表示して確認しています。
/LDコマンド実行時の表示から、ファイルの終わりは8317Hであることがわかります。
ダンプした内容を見ると、改行コード(0D0A)が2回使われて、そこで終わっています。
この後に1Aを追加します。
メモリの中味を書き換えるにはCMコマンドを使います。
8318Hの中味を1Aに書き換えました。
念の為にもう一度DMコマンドで中味を確認しています。
8318Hは1Aになっています。
ここまでで作業は終了しましたから、もう一度CP/Mに戻ります。
jp bc00[Enter]でCP/Mに戻りました。

いかがでしょうか?
ND80ZVのZB3BASICシステムはメチャメチャ便利でしょう。
もう、自由自在、といった感じです(こんなに便利なものは、ありませんですよぉ)。

変更した内容をあらためてt1520.txtの名前で仮想フロッピーディスクに保存するために、
save 3 t1520.txt[Enter]
を実行しています。

このあと、もう一度
type t1520.txt[Enter]
を実行したところ、今度はちゃんと本来のテキストの終わりまで表示して終わりました(ゴミは表示されなくなりました)。
めでたし、めでたし、です。

そこで、あらためて
t1520 t1520.txt[Enter]
を実行しましたら。
やっぱりゴミが表示されてしまいました。
えええ?
どうして???

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

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