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

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

[第35回]

●CP/Mソースプログラムの再変更

[第32回]で、とりあえずのCP/Mソースプログラムの修正作業は完了です、と書きましたが、いろいろ作業を進めておりますと、だんだんと理解が深まってきて、さらに直したいところなどが出て来てしまいます。

とは言いましても、今回これから説明しますところは、変更しなくても実行には影響はありません。
さらに言えば、もともと仮のRAMディスクでのテストですし、どうせメモリ増設基板を接続することになりましたら、いやでも再変更しなければなりませんから、そのままにしておいても、別にどうということはありません。

しかし。
そうだとしても、やっぱりこのままにしておくのは、ちょっと気が引けます。

気になって、直しておきたいと思いますのは、BIOSの先頭部分に置いた、ディスクパラメータの位置のことなのです。
下は[第32回]でお見せしたリストの先頭部分です。

;*************** BIOS DATA AREA ******************************
;
DIRBF EQU 0B800H;128bytes
;
CSV00 EQU 0B880H;8bytes 
ALV00 EQU 0B888H;3bytes
;
;   DISK PARAMETER BASE
;
DPBASE: 
;
;drive No.0 (a drive)
        DEFW    0               ;XLATE
        DEFW    0               ;scratch1
        DEFW    0               ;scratch2
        DEFW    0               ;scratch3
        DEFW    DIRBF           ;address of dirbf.
        DEFW    DPTOP           ;address of disk parameter block.
        DEFW    CSV00           ;address of check vector.
        DEFW    ALV00           ;address of allocation vector (bit map).
;
;
DPTOP:DEFW      16              ;sectors per track from bios.
        DEFB    2               ;block shift.sector in a block 128*2^n
        DEFB    3               ;block mask.sector no. in a block - 1
        DEFB    0               ;extent mask.
        DEFW    23              ;disk size (number of blocks-1).
        DEFW    31              ;directory size.(max file name no.-1)
        DEFW    0C0H            ;storage for first bytes of bit map (dir space used).
        DEFW    8               ;check sum vector size
        DEFW    0               ;offset. first usable track number.
;
;**************************************************************
;*
;*        B I O S   J U M P   T A B L E
;*
;**************************************************************
;
BOOT:   JP      BOOTJ
WBOOT:  JP      WBOOTJ
CONST:  JP      CONSTJ
CONIN:  JP      CONINJ
CONOUT: JP      CONOUTJ
LIST:   JP      LISTJ
PUNCH:  JP      PUNCHJ
READER: JP      READERJ
HOME:   JP      HOMEJ
SELDSK: JP      SELDSKJ
SETTRK: JP      SETTRKJ
SETSEC: JP      SETSECJ
SETDMA: JP      SETDMAJ
READ:   JP      READJ
WRITE:  JP      WRITEJ
PRSTAT: JP      PRSTATJ
SECTRN: JP      SECTRNJ
;
;BIOS ROUTINE
;

DISK PARAMETERが、BIOSのジャンプテーブルの前にあります。
いろいろとやっておりますうちにわかってきたことなのですが、このデータはCP/Mの暗黙のルールとして、BIOSジャンプテーブルの後に置くもののようです。
そこで、そっくりそのまま移動して下のようにします。

;*************** BIOS DATA AREA ******************************
;
DIRBF EQU 0B800H;128bytes
;
CSV00 EQU 0B880H;8bytes 
ALV00 EQU 0B888H;3bytes
;
;**************************************************************
;*
;*        B I O S   J U M P   T A B L E
;*
;**************************************************************
;
BOOT:   JP      BOOTJ
WBOOT:  JP      WBOOTJ
CONST:  JP      CONSTJ
CONIN:  JP      CONINJ
CONOUT: JP      CONOUTJ
LIST:   JP      LISTJ
PUNCH:  JP      PUNCHJ
READER: JP      READERJ
HOME:   JP      HOMEJ
SELDSK: JP      SELDSKJ
SETTRK: JP      SETTRKJ
SETSEC: JP      SETSECJ
SETDMA: JP      SETDMAJ
READ:   JP      READJ
WRITE:  JP      WRITEJ
PRSTAT: JP      PRSTATJ
SECTRN: JP      SECTRNJ
;
;   DISK PARAMETER BASE
;
DPBASE: 
;
;drive No.0 (a drive)
        DEFW    0               ;XLATE
        DEFW    0               ;scratch1
        DEFW    0               ;scratch2
        DEFW    0               ;scratch3
        DEFW    DIRBF           ;address of dirbf.
        DEFW    DPTOP           ;address of disk parameter block.
        DEFW    CSV00           ;address of check vector.
        DEFW    ALV00           ;address of allocation vector (bit map).
;
;
DPTOP:DEFW      16              ;sectors per track from bios.
        DEFB    2               ;block shift.sector in a block 128*2^n
        DEFB    3               ;block mask.sector no. in a block - 1
        DEFB    0               ;extent mask.
        DEFW    23              ;disk size (number of blocks-1).
        DEFW    31              ;directory size.(max file name no.-1)
        DEFW    0C0H            ;storage for first bytes of bit map (dir space used).
        DEFW    8               ;check sum vector size
        DEFW    0               ;offset. first usable track number.
;
;BIOS ROUTINE
;

BIOSジャンプテーブルの置かれているアドレスはどこでもよい、というものではないらしく、BIOSジャンプテーブルの先頭アドレス(BOOT:のアドレス)が××00Hになるように配置するもののようです。
ソースプログラムでは、CCP、BDOSに続いて記述するのですが、このときディスクパラメータがBIOSジャンプテーブルの前にあると、ジャンプテーブルアドレスを××00Hに固定しにくくなります。
もともとジャンプテーブルはその名の通り、各処理プログラムへのジャンプ命令を集めたものですから、BIOSの先頭に置くのが理にかなっています。

ということで、せっかく[第32回]でコピーしてCP/Mソースプログラムに貼り付けていただいたのですが、上のリストのようにディスクパラメータ部分をBIOSジャンプテーブルの後に変更していただきますようお願いいたします。

念の為に、変更後のBIOSルーチン全体のリスト([第32回]のリストを、ディスクパラーメータ部分のみ切り取って、BIOSジャンプテーブルの後に貼り付けたもの)を下に表示しておきます。

;*************** BIOS DATA AREA ******************************
;
DIRBF EQU 0B800H;128bytes
;
CSV00 EQU 0B880H;8bytes 
ALV00 EQU 0B888H;3bytes
;
;**************************************************************
;*
;*        B I O S   J U M P   T A B L E
;*
;**************************************************************
;
BOOT:   JP      BOOTJ
WBOOT:  JP      WBOOTJ
CONST:  JP      CONSTJ
CONIN:  JP      CONINJ
CONOUT: JP      CONOUTJ
LIST:   JP      LISTJ
PUNCH:  JP      PUNCHJ
READER: JP      READERJ
HOME:   JP      HOMEJ
SELDSK: JP      SELDSKJ
SETTRK: JP      SETTRKJ
SETSEC: JP      SETSECJ
SETDMA: JP      SETDMAJ
READ:   JP      READJ
WRITE:  JP      WRITEJ
PRSTAT: JP      PRSTATJ
SECTRN: JP      SECTRNJ
;
;   DISK PARAMETER BASE
;
DPBASE: 
;
;drive No.0 (a drive)
        DEFW    0               ;XLATE
        DEFW    0               ;scratch1
        DEFW    0               ;scratch2
        DEFW    0               ;scratch3
        DEFW    DIRBF           ;address of dirbf.
        DEFW    DPTOP           ;address of disk parameter block.
        DEFW    CSV00           ;address of check vector.
        DEFW    ALV00           ;address of allocation vector (bit map).
;
;
DPTOP:DEFW      16              ;sectors per track from bios.
        DEFB    2               ;block shift.sector in a block 128*2^n
        DEFB    3               ;block mask.sector no. in a block - 1
        DEFB    0               ;extent mask.
        DEFW    23              ;disk size (number of blocks-1).
        DEFW    31              ;directory size.(max file name no.-1)
        DEFW    0C0H            ;storage for first bytes of bit map (dir space used).
        DEFW    8               ;check sum vector size
        DEFW    0               ;offset. first usable track number.
;
;BIOS ROUTINE
;
;zb3routine
;
ADISP EQU 1015H
ZREENT EQU 1033H
SOUT EQU 10ABH
SIN EQU 10AEH
;
TRKADRS EQU 0BB00H
SCTADRS EQU 0BB02H
DMAADRS EQU 0BB04H
DRVNO   EQU 0BB06H
DISKTOP EQU 8800H
;
SETENTRY:LD HL,REENT
        LD A,0C3H
LD (HL),A
        INC HL
        LD DE,SETEN2
        LD (HL),E
        INC HL
        LD (HL),D
SETEN2:LD HL,IOBYTE
        XOR A
        LD (HL),A
        INC HL
        LD (HL),A
        INC HL
        LD A,0C3H
        LD (HL),A
        INC HL
        LD DE,FBASE
        LD (HL),E
        INC HL
        LD (HL),D
        JP CBASE
;
BOOTJ:XOR A
        LD (IOBYTE),A
        JP      CBASE
;
WBOOTJ: LD A,(IOBYTE)
        LD C,A
        JP      CBASE
;
;CONSOLE STATUS
;
CONSTJ:LD A,07
        CALL SOUT
        CALL SIN
        CP 20H
        RET NZ
        XOR A
        RET
;
;CONSOLE INPUT
;
CONINJ: LD A,5;1chr IN,nodp
        CALL SOUT
        CALL SIN
        RET
;
;CONSOLE OUT
;
CONOUTJ:LD A,C
        CP 0AH;12.1.8
        JP NC,ADISP ;11.12.29
        XOR A
        RET
;
;PRINTER OUT
;
LISTJ:  RET
;
;PUNCHER OUT
;
PUNCHJ: RET
;
;READER IN
;
READERJ:        RET;JP  0
;
;SEEK HOME POSITION
;
HOMEJ:  LD HL,DISKTOP
        LD (TRKADRS),HL
        LD (SCTADRS),HL
        XOR A
        RET
;
;SELECT DRIVE PARAMETER SET
;
SELDSKJ:LD HL,DPBASE
        LD A,C
        LD (DRVNO),A
        RET
;
;SET TRKADRS
;
SETTRKJ:LD HL,DISKTOP
        LD DE,800H
        INC C
STTRK1: DEC C
        JP Z,STTRK9
        ADD HL,DE
        JP STTRK1
STTRK9:LD (TRKADRS),HL
        XOR A
        RET     
;
;SET SCTADRS
;
SETSECJ:LD HL,(TRKADRS)
        LD DE,80H
        INC C
STSCT1: DEC C
        JP Z,STSCT9
        ADD HL,DE
        JP STSCT1
STSCT9:LD (SCTADRS),HL
        XOR A
        RET     
;
;SET DMAADRS
;
SETDMAJ:LD H,B
        LD L,C
        LD (DMAADRS),HL
        XOR A
        RET
;
;READ SECTOR
;
READJ:LD HL,(DMAADRS)
        EX DE,HL
        LD HL,(SCTADRS)
READJ1: LD C,80H
READJ2:LD A,(HL)
        LD (DE),A
        INC HL
        INC DE
        DEC C
        JP NZ,READJ2
        XOR A
        RET
;
;WRITE SECTOR
;
WRITEJ: LD HL,(SCTADRS)
        EX DE,HL
        LD HL,(DMAADRS)
        JP READJ1
;
;PRINTER STATUS
;
PRSTATJ:        RET
;
;sector translator
;
SECTRNJ:LD L,C
        LD H,B
        RET;
;
;*
;******************   E N D   O F   C P / M   *****************
;*
END;

そのように変更していただいたら、CPM22E.TXTという名前で保存してください。
このファイルを[第34回]で説明しましたように、Z80アセンブラZASM1.64でアセンブルします。



●cpm22.z80のバグ

上の作業に関連していろいろ調べておりましたら、今回の作業のもとになっております、cpm22.z80にバグがあるのに気が付きました。

上で説明をしましたように、BIOSジャンプテーブルは、BDOSの後に続いて記述していますが、そのアドレスは××00Hにするのが、CP/Mの暗黙のルールのようです。
そのためには、BDOSとBIOSの間にダミーエリアを置いてそこでアドレスを調整するという方法が考えられます。

BDOSとBIOSの間にある、よくわからないエリアが、そのダミーデータのようです(「Extra space?」とコメントされている部分)。



ここでは4バイトのスペースがそれに相当するように思われます。
その上のCKSUMTBL:は16バイトあって、それにはその上のコメントで、ディレクトリバッファのチェックサム用エリアだと説明してあります。
そして接続可能な最大ドライブ数(16台)のそれぞれ用に1バイトなので16バイトである、と書かれています。

本当か?
それはおかしいのでは?
と疑問を感じたのがそもそものきっかけでした。

ディレクトリのチェックサムとしては[第33回]で説明をいたしました。
CSVがそれです。
ディスクごとに1バイトではなくて、ディレクトリのセクタごとに1バイトが必要です(そのはずです)。
それなら、上で書かれている説明は間違っていることになります。

そしてもしもこのエリアが各ドライブのCSVエリアのアドレスを格納するためのものだったとすれば、各ドライブに2バイト必要ですから、16バイトでは足りません。
するとここは、一体何のためのエリアなのでしょうか?
それを探るために、CKSUMTBLで検索してみました。
その結果意外なことがわかりました。


検索の結果、CKSUMTBLを参照しているのは、下のCHECKDIRルーチンの中の2201行と2210行の2ヶ所のみであることがわかりました。



これを見ると、やはりアドレスの格納用に使われているようですから、2バイトです。
そしてCKSUMTBLに値を設定しているのは、下の1ヶ所のみです。



TRKSECというルーチンは、ディレクトリアクセス以外でも使われているようですが、とにかくディレクトリを読んだときに、そのディレクトリがあるセクタナンバー(0から始まる連番か?)がCKSUMTBLに入るようです。
さきほどのルーチンでは、その値とALLOC1の値とを比較することで、全ディレクトリのチェックサムが完了したかどうかを確認しているようです。
ALLOC1については、[第13回]で説明をいたしました。CKVSの誤記のようです。
CKVSにはディレクトリのセクタ数が入ります([第33回])。

ところで上記のCKSUMTBLに関わるルーチンのどこにも、CKSUMTBLの後方のアドレスを使うところは見当たりませんでした。
ということは、CKSUMTBLとしては2バイトのみが使われているだけ、ということになます。
つまり、そのところは、下のように書くのが正しいと思います。



CKSUMTBL:の2バイトの後にあるエリアは、上の方で書きましたように、BIOSジャンプテーブルの開始アドレスを××00Hにするためのダミーだと思います。

なんだ。こんなことぐらいなら、バグというほどのものでもないじゃないか。
ええ。
これ位のことなら、バグではありません。

じつは。
バグは、このCKSUMTBLに関係する、別のところで偶然みつけてしまったのです。
上のところでお見せした、CKSUMTBLを参照しているこちらのルーチンを見ておりましたら、2207行でCALLしておりますCHECKSUMルーチンではどんな計算をしているのだろう?
という興味がわいてきたのです。
そこで、そのCHECKSUMルーチンを見てみました。
そうしましたら、そこにバグがあったのです。

これがCHECKSUMルーチンです。
ここのどこにバグがあるか、おわかりになりますでしょうか?

                     	;
                      	;   Compute the check-sum for the directory buffer. Return
                      	; integer sum in (A).
                      	;
  C8FA  0E80          	CHECKSUM: LD	C,128		;length of buffer.
  C8FC  2AC0D1        		LD	HL,(DIRBUF)	;get its location.
  C8FF  AF            		XOR	A		;clear summation byte.
  C900  C600          	CHKSUM1:ADD	A,M		;and compute sum ignoring carries.
  C902  23            		INC	HL
  C903  0D            		DEC	C
  C904  C200C9        		JP	NZ,CHKSUM1
  C907  C9            		RET	

あ。
これは次回までの宿題ということにいたしましょう。

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

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