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

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

[第187回]


●ブレークプログラム(CP/M互換DOSのための変更その2)

前回はブレークポイントの設定(BPコマンド)プログラムについて説明をしました。
今回はブレークポイントアドレスに仕掛けられたトラップ(FFコード)によって0038H番地からジャンプして実行されるブレーク処理プログラムについて説明をします。

CP/M互換DOSのための変更を行なう前のプログラムリストは[第182回]でお見せしています。
下は変更後のリストです。

              ;;;
              ;;;BREAK ENTRY
1B53 F3       BROUT:DI
1B54 E3       EX (SP),HL
1B55 2B       DEC HL
1B56 229BF0   LD (PCL),HL   
1B59 E1       POP HL
1B5A ED7399F0 BROUT1:LD (SPBF),SP;from ZBDOS
1B5E 3198F0   LD SP,IREG   
1B61 DDE5     PUSH IX
1B63 FDE5     PUSH IY
1B65 F5       PUSH AF
1B66 C5       PUSH BC
1B67 D5       PUSH DE
1B68 E5       PUSH HL
1B69 08       EX AF,AF'
1B6A F5       PUSH AF
1B6B D9       EXX
1B6C C5       PUSH BC
1B6D D5       PUSH DE
1B6E E5       PUSH HL
1B6F ED57     LD A,I
1B71 3298F0   LD (IREG),A   
1B74 2100F5   LD HL,STC
1B77 1100ED   LD DE,STCWK
1B7A 010003   LD BC,$0300
1B7D EDB0     LDIR
1B7F 3100F8   LD SP,SPTOP
1B82 3AE6FE   LD A,(EIMK)
1B85 B7       OR A
1B86 CA891B   JP Z,BROUT2
1B89 2A80F0   BROUT2:LD HL,(BRKAD)
1B8C 3A82F0   	LD A,(BRKBF)
1B8F CDE11C   	CALL MEMWR2
1B92 CD0E1B   	CALL RGDSP
1B95 C3181C   	JP BPST5

ND80ZVのシステムROMに書かれているZB3BASICの本来のブレーク動作は、命令コードFF(RST7)を実行することで、アドレス1B53Hにジャンプしてきます。
このブレーク処理のエントリ部分は変更後も変更前と同じですが、プログラム変更によって全体のアドレスが変更前とは少し変わっています。

説明の都合でまず最初にプログラムの終わりでレジスタダンプを行なっているところから説明をします。
アドレス1B8FHにCALL MEMWR2があります。
ここではブレークアドレスに、保存してあった本来の命令コードを戻します。

MEMWR2は[第165回]で説明をしました。
LD (HL),Aを変更して、その代わりにこのMEMWR2を実行します。
対象になるメモリアドレスはHLレジスタにあります。
Hレジスタの正負を判定して、Hの値が正のとき(00〜7Fのとき)はCP/M互換DOSのBIOSのRAMWRにジャンプします。
負のとき(80〜FFのとき)は、
LD (HL),A
を実行します。

この部分はZB3BASICプログラムのもとになった別のシステム用の処理プログラムが残っていたままになっていましたので、この機会に削除したつもりだったのですが、まだ削除できていないところが残っていました。
1B82H〜1B88Hは不要でした。

フルRAMのための変更部分はこのほかにもあります。
フルRAMのシステムに対応するために、処理の途中の1B5AHにエントリするためのラベルの追加(BROUT1)が行なわれています。
フルRAMの状態では、0000H〜7FFFHの範囲もRAMが選択されるため、このブレーク処理プログラムを含め、ND80ZVのシステムROM全体が非アクティブの状態になります。

ということはブレークした時点では、ROMに書かれているこのブレーク処理プログラムもアクセスできません。
フルRAM構成のときは、0038Hに書かれるRST7処理(つまりブレーク処理)へのジャンプ命令も、そのジャンプ先はBIOSのルーチンになります。
そこで必要な処理を行なった後、ROMをアクティブにして、このブレーク処理ルーチンが実行されます。

そのとき、BIOSでの処理の都合から、本来のブレークエントリではなくて、新たに設けた途中のエントリアドレス1B5AH(BROUT1)へのジャンプが行なわれます。

なお、このような追加を行なう場合に、直接1B5AHへのジャンプ命令をBIOSに書いてしまうと、将来さらなるプログラム変更が行なわれたりすると、ひょっとするとBROUT1のアドレスも動いてしまうかも知れません。
そこで面倒ですが、他のプログラムからコールされたりジャンプされたりするアドレスは、ちょうどBIOSで行なわれているように、プログラムの先頭部分にエントリのためのジャンプ命令を配置して、そこからのジャンプによってエントリするようにしておきます。

ブレーク処理全体が属しているのは、ZB3BASICのエントリプログラムです。
下はその先頭にあるジャンプテーブル部分です。
一番下にBROUT1へのジャンプ命令が追加されています。

              ;;;
1800 C35418   JP START
1803 C3A418   JP ENTRY
1806 C35519   JP SDTIN
1809 C31510   JP ADISP
180C C3AE10   JP SIN
180F C37F19   JP ASOUT
1812 C31D19   JP LNSRC
1815 C3F918   JP ENT4
1818 C38F19   JP AUTO
181B C3DD19   JP MVDBI
181E C3F519   JP DM
1821 C3651A   JP CM
1824 C3D11B   JP BP
1827 C3981B   JP RT
182A C3F71A   JP IN
182D C3D41A   JP OUT
1830 C3AE1C   JP LCDOT
1833 C3B01C   JP LINIT
1836 C3B11C   JP JPIN
1839 C3AF1C   JP LCDINSB
183C C3C31C   JP RRCOPYSB
183F C30E1B   JP RGDSP
1842 C3AE10   JP SIN;   from INPUT$
1845 C3A21C   JP SIN_NODTRT;  from INKEY$,INPUT$
1848 C3741C   JP LD
184B C38B1C   JP SV
184E C30B1A   JP DMSB
1851 C35A1B   JP BROUT1
              ;;;

●BIOSのRST7ルーチン

それでは今度はBIOSのRST7ルーチンについて説明をします。
フルRAMの構成での0038Hに書かれるRST7処理プログラムへのジャンプ命令は、CP/M互換DOSの初期ブート部分(下のリスト)で設定されます。

              ;
              ;BIOS ROUTINE
              ;
D277 3100F8   SETENTRY:LD SP,SPTOP
D27A AF       	XOR A
D27B 3204D6   	LD (CURDRV),A
              ;here,dos system reload
D27E 3100F8   WBOOTJ:LD SP,SPTOP
D281 3EFF     	LD A,FF
D283 D39C     	OUT (9C),A
D285 213800   	LD HL,RST7
D288 3EC3     	LD A,C3
D28A 77       	LD (HL),A
D28B 23       	INC HL
D28C 11CAD2   	LD DE,RST7BRK
D28F 73       	LD (HL),E
D290 23       	INC HL
D291 72       	LD (HL),D
              ;

ここでブレーク処理へのエントリ(RST7BRK)へのジャンプ命令が書き込まれます。
そして下がそのRST7BRKルーチンです。

D2CA F3       RST7BRK:DI
D2CB 3278D5   	LD (BRKWK),A
D2CE E3       	EX (SP),HL
D2CF 2B       	DEC HL
D2D0 229BF0   	LD (PCL),HL   
D2D3 E1       	POP HL
D2D4 3E00     	LD A,00;can't use XOR A!
D2D6 D39C     	OUT (9C),A;select 0-7fff ROM
D2D8 3A78D5   	LD A,(BRKWK)
D2DB C35118   	JP BROUT1

ROMに書かれているブレーク処理ルーチンを実行するためには、RAMとROMを切り換えなくてはなりません。
そのためにはI/Oアドレス9CHに00をOUTするのですが、そのときどうしてもAレジスタを使うことになります。
そのために、まずAレジスタを保存しておく必要があります。
RAMとROMを切り換えてから、Aレジスタの値を元に戻して、それからROMのブレーク処理ルーチンにジャンプします。

このプログラムを書いた時点ではいろいろ試行錯誤をしていたものですから、ここにありますように、ブレーク処理プログラムの先頭のPC(プログラムカウンタ)の保存のところを、BIOS側で実行するようになっていますが、今あらためて考えてみますと、ここはROMの側で実行しても特に問題はありませんでした。
その時点では気がつかないことでも、少し時間が経ってからあらためて見てみると、このように無駄な事をやっているなあと気がつくことが出てきます。
毎日記事を書くことはなかなか負担ではありますが、こうやって記事にまとめることで、はじめて気がつくこともありますので、その意味では結構自分のためにも役立っていると思います。

なお、上のリストのコメントにありますように、普通Aレジスタに00を入れるにはXOR Aを使いますが、ここでそれを使うと、フラグが変化してしまいます。
ですからここでは
LD A,00
を使っています。

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

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