復活!CP/M ワンボードマイコンでCP/Mを!
CP/MがTK−80互換のワンボードマイコンの上で復活します
ND80ZVとMYCPU80の上でCP/Mが走ります!
[第72回]
●ファンクションコール0BHの動作解析
今回の説明はちょっと難しいかもしれません。
私の頭の中では理解できているのですが、それをうまく説明できるかどうかがちょっと難しいように思います。
前回BIOSのコンソールステータスチェックルーチンにまずいところがあることがわかって、それを直したのですが、Ctrl−Sでポーズはするのですが、そのあとCtrl−D(本来はCtrl−C)を入力してもブレイクしてくれません。
ファンクションコール0BHの処理の中で何かおかしなことがおきているようです。
その処理ルーチンは前回もお見せしました、下のリストの部分です。
こういうときに通常ならばブレイクポイントを設定して、途中でブレイクさせながら、レジスタの中味を確認していくことで、問題の有る部分を炙り出すことができます。
しかし今回はそういうわけにはいきません。
キー入力を伴うプログラムにその手法は使えないことが多いのです。
肝心の部分はリアルタイムであることが要求されるからです。
そういう場合には、簡便な方法として、レジスタの値をワークメモリに書き込んでおいて、あとからそれを参照する、というテクニックを使います。
そこで、上のプログラムを下のように直しました。
ファンクションコール0BHをコールすると、このCKCONSOLルーチンが実行されます。
ここで想定外の何かがおきているようなので、何がおきているのかを可視化するための変更です。
適当なワークエリアを用意し、そこにポイントになる値を書き込むようにします。
CKCONSOLにエントリすると最初にCHARBUFの値をチェックします。
ここには、前回CKCONSOLが実行されたときに検出されたキー入力コードが収められています。
そこにすでに文字コードが入っていたら、BIOSをコールしないでAレジスタに01を入れて(つまりキー入力有りにして)リターンします。
このCHARBUFの値はテストプログラムでも参照しているのですが、念の為にWK1にも入れることにします。
それが1376のLD (WK1),Aです。
CHARBUFが空(00)のときは、BIOSのCONSTルーチン(コンソールステータスチェック)をコールします。
CONSTは前回修正して、キー入力有りのときは入力された文字コードのビット0を1にしてリターンします。
そのリターンされてきた値をWK2に入れます。
それが1380のLD (WK2),Aです。
その値のビット0が0ならば、入力無しの印として、Aレジスタを00にしてリターンします。
ここで入力有りならばあらためてBIOSのCONINルーチン(コンソール入力)をコールします。
ここでキー入力された文字コードをWK3に入れます。
以上のように変更して、それをCPM22I2.TXTというファイル名で保存します。
しかし今回テストのためにプログラムに追加修正をしたために、ほかにも直さなければならないところがでてきてしまいました。
プログラムの途中で命令を追加したために、BIOSのエントリアドレスが後にずれてしまいます。
3バイトのLD命令を3ヶ所追加しましたから、9バイト後にずれてしまいました。
これを補正しなければなりません。
なかなかに面倒です。
こういうことにならないように、必要なジャンプテーブルやワークアドレスはプログラムの先頭にまとめてしまうとよいのですが、CP/Mのソースプログラムがそのような形になっていないものですから、面倒でもそれに従うしかありません。
途中をなんとか9バイト縮めなければいけません。
さてどうするか?
そこで、[第67回]でシステムスタックを移動したことを思い出しました。
確か元のスタックエリアがそのまま残っていたはずです。
ここでした。
この部分を完全に削除してしまえば全体が16バイト縮まります。
そこで、1209行を下のようにコメント行にしました。
このままだと、16−9=7バイト分、逆にBIOSのエントリアドレスが前にきてしまいます。
そこで、今度はBDOSの最後の部分に7バイトのダミーを追加します。
さきほどのCKCONSOLのところで6行追加したために、行番号は変わってしまいましたが、元の3709行に7バイト追加を行なっています(新3715行)。
これであらためてCPM22I2.TXTとしてセーブしたうえで、アセンブルして、BIOSのエントリ部が移動していないことを確認しました。
●テストプログラムの変更作業
今度はテストプログラムの変更作業を行ないます。
ファンクションコール0BHの処理ルーチンで保存した値をモニタする部分をつけ加えます。
下がそのように変更したあとのテストプログラムです。
リストが長くなりますから、表示のためのサブルーチン部分は省略してあります。
; BDOS function0B test fnc0bt2 ;2012/3/26 ; ORG $8100 FCALL=$8005 CHARBUF=$C707 WK1=$8300 WK2=$8301 WK3=$8302 ; LOOP:LD C,0B CALL FCALL PUSH AF LD A,(WK1) CALL B2HEXDP LD A,(WK2) CALL B2HEXDP LD A,(WK3) CALL B2HEXDP POP AF PUSH AF CALL B2HEXDP LD A,(CHARBUF) CALL B2HEXDP POP AF OR A JP NZ,KEYIN NEXT:CALL SPDP JP LOOP KEYIN:LD A,2A;'*' CALL ADP LD C,01 CALL FCALL PUSH AF LD A,3A;':' CALL ADP POP AF PUSH AF CALL B2HEXDP POP AF PUSH AF CALL ADP POP AF CP 1A;^Z RET Z JP NEXT ; |
2012/3/26 20:6 fnc0bt2.txt END=81B2 ; BDOS function0B test fnc0bt2 ;2012/3/26 ; ORG $8100 FCALL=$8005 CHARBUF=$C707 WK1=$8300 WK2=$8301 WK3=$8302 ; 8100 0E0B LOOP:LD C,0B 8102 CD0580 CALL FCALL 8105 F5 PUSH AF 8106 3A0083 LD A,(WK1) 8109 CD7781 CALL B2HEXDP 810C 3A0183 LD A,(WK2) 810F CD7781 CALL B2HEXDP 8112 3A0283 LD A,(WK3) 8115 CD7781 CALL B2HEXDP 8118 F1 POP AF 8119 F5 PUSH AF 811A CD7781 CALL B2HEXDP 811D 3A07C7 LD A,(CHARBUF) 8120 CD7781 CALL B2HEXDP 8123 F1 POP AF 8124 B7 OR A 8125 C22E81 JP NZ,KEYIN 8128 CD5981 NEXT:CALL SPDP 812B C30081 JP LOOP 812E 3E2A KEYIN:LD A,2A;'*' 8130 CD5B81 CALL ADP 8133 0E01 LD C,01 8135 CD0580 CALL FCALL 8138 F5 PUSH AF 8139 3E3A LD A,3A;':' 813B CD5B81 CALL ADP 813E F1 POP AF 813F F5 PUSH AF 8140 CD7781 CALL B2HEXDP 8143 F1 POP AF 8144 F5 PUSH AF 8145 CD5B81 CALL ADP 8148 F1 POP AF 8149 FE1A CP 1A;^Z 814B C8 RET Z 814C C32881 JP NEXT ; |