復活!CP/M ワンボードマイコンでCP/Mを!
CP/MがTK−80互換のワンボードマイコンの上で復活します
ND80ZVとMYCPU80の上でCP/Mが走ります!
[第255回]
●LLISTとLPRINTが駄目だった理由
前回からの続きです。
ファンクションコール05のテストプログラムでは正しくプリントアウトできたのに、MBASICのLLISTとLPRINTを試してみましたら、まともに動作しませんでした。
いったいなぜ?
その解決の糸口としまして、前回はオリジナルの(実はオリジナルではなくて逆アセンブル版の)CP/Mソースのファンクション05がそのままBIOSのLISTルーチンにジャンプしているので、CP/M互換DOSでもそのようにしたのですが、そこがおかしいのではないか、という意味のことを書きました。
ファンクションコールにつきましては[第196回]で一覧表にまとめています。
下にその一部を切り取って示します。
ファンクション(Cレジスタにセットする値) | 機能 | パラメータセット DEまたはEに値をセットする |
結果 |
0 00(16進) | システムリセット | なし | システムがリセットされる |
1 01 | コンソール入力 | なし | A=文字コード |
2 02 | コンソール出力 | E=文字コード | 文字が表示される |
3 03 | リーダー(RDR)入力 | なし | A=文字コード |
4 04 | パンチ(PUN)出力 | E=文字コード | PUN:に出力される |
5 05 | リスト(LST)出力 | E=文字コード | LST:(プリンタ)に出力される |
注目すべきところを着色して示しました。
ファンクションコールではファンクションbCレジスタに入れて、パラメータは8ビットならEレジスタに、16ビットならDEレジスタにいれた上で0005Hをコールします。
ですからファンクションコール05ではプリントアウトする文字コード(ASCIIコード)をEレジスタに入れます。
ここまでのところには間違いはありません。
そしてファンクションコール05の実態はBIOSのプリンタ出力ルーチンそのものでしたので、そのままBIOSにジャンプするようにしました。
そこが間違いだったのです。
当然それを受けてBIOSのプリンタ出力ルーチンもEレジスタから文字コードを取り出してそれをプリンタに出力するようにプログラムしました。
うむ。
いいじゃないの、それで。
どこも間違ってはいないのじゃありませんか?
いえ。実は間違っていたのです。
BIOSの先頭部分には、マシンに直結する部分のプログラムへのジャンプ命令がずらりと並んでいます。
CP/M互換DOSのBIOSのジャンプテーブルについては、いままで説明をしていませんでした。
そこで、下に簡単に表にまとめて示すことにしました。
ファンクションコールはCレジスタにファンクションbセットして0005Hをコールしましたが、BIOSは下の表にある各機能のアドレスをコールします。
アドレス | 機能 | パラメータセット BCまたはCに値をセットする |
結果 |
D200 | コールドブート | なし | システムが初期ブートされる |
D203 | ウォームブート | なし | アドレス0000Hにジャンプしてリブートする |
D206 | コンソールステータス | なし | READY:A=FF,BUSY:A=00 |
D209 | コンソール入力(キーボード入力) | なし | A=入力文字コード |
D20C | コンソール出力(画面表示) | C=文字コード | 画面に表示される |
D20F | リスト出力(プリンタ出力) | C=文字コード | LST:(プリンタ)に出力される |
D212 | パンチ出力(RS232C送信) | C=文字コード | 1文字分のコードが232C送信される |
D215 | リーダー入力(RS232C受信) | なし | A=受信データ |
D218 | ディスクホームシーク | なし | ディスクがホームへシークされる |
D21B | セレクトディスク | C=ドライブナンバー(A=0,B=1…) | 指定したディスクが選択される |
D21E | セットトラック |
BC=トラックナンバー | 指定したトラックが選択される |
D221 | セットセクタ | BC=セクタナンバー | 指定したセクタが選択される |
D224 | セットDMAアドレス | BC=DMAバッファアドレス | ディスクリード、ライト時のバッファアドレスがセットされる |
D227 | ディスクリード |
なし | ディスクから1セクタデータがDMAバッファに読み込まれる |
D22A | ディスクライト | なし | DMAバッファのデータがディスクに書き込まれる |
D22D | リストステータス(プリンタステータス) | なし | READY:A=FF,BUSY:A=00 |
D230 | セクタトランスレータ | BC=論理セクタナンバー | 論理セクタが物理セクタに変換される。HL=物理セクタナンバー |
表の一番上のパラメータセットの説明をご覧ください。
「BCまたはCに値をセットする」と書いてあります。
そうだったのです。
面倒なことに、ファンクションコールでは、パラメータはDEまたはEレジスタにセットするのに対し、BIOSルーチンでは、BCまたはCレジスタにセットするというルールになっていたのです。
しかし、それはそれとして、ファンクションコール05では出力文字コードをEレジスタに入れているので、それをそのままBIOSにもってきて、BIOSのプリンタ出力ルーチンでも、Eレジスタから文字コードを読み出して、それをプリンタに出力するようにしても、正しくプリントアウトされるはずなので、それのどこがいかんのか?
そうなのですよねえ。
もしも[第249回]でお見せしましたように、プリンタ出力の場合には必ずファンクションコール05を使ってくれれば、なんの問題もありませんのです。
しかし。
プログラムの上級者ともなりますと、いちいちファンクションコールなどというものを使うのはだんだんと面倒になってきます。
いっそBIOSルーチンを直接コールしてしまったほうが早いのではないの?
おそらくそういうわけでありましょう、MBASICのLLIST、LPRINTは、どうやらファンクションコール05を使うのではなくて、直接BIOSのプリンタ出力ルーチンをコールしているようなのです。
もうおわかりいただけたことと思います。
MBASICでLLISTとLPRINTが働かなかったわけが。
そうだったのです。
私がそこのところを深く考えずに、BIOSのプリンタ出力ルーチンでもEレジスタの値を文字コードとしてプリンタに出力するようにしていたため、おそらくBIOSのプリンタ出力ルーチンを直接コールしているらしいMBASICでは(当然文字コードはCレジスタに入れるはず)、まともな出力結果が得られなかったのです。
そこで。
[第248回]でお見せしましたBIOSのプリンタ出力ルーチンを下のように修正しました。
;PRINTER OUT D3A5 DB82 LISTJ:IN A,(82) D3A7 E680 AND 80 D3A9 C2A5D3 JP NZ,LISTJ D3AC 79 LD A,C D3AD D380 OUT (80),A D3AF AF XOR A D3B0 D383 OUT (83),A D3B2 00 NOP D3B3 3C INC A D3B4 D383 OUT (83),A D3B6 C9 RET ; |
;PRINTER OUTPUT FCALL 05 ; C86A 4B LSTOUT:LD C,E C86B C30FD2 JP B_LIST |
B>mbasic BASIC-80 Rev. 5.21 [CP/M Version] Copyright 1977-1981 (C) by Microsoft Created: 28-Jul-81 25400 Bytes free Ok load "ptest1" Ok list 10 LPRINT "abcxyz" 20 LPRINT "12345" 30 LPRINT "7890"; 40 LPRINT "hij" 50 PRINT "end" Ok llist run end Ok llist Ok system |
そして、これがそのときのプリンタ出力結果です。
正しくプリンタ出力されるようになりました。
やっと。
一件落着いたしました。
ワンボードマイコンでCP/Mを![第255回]
2012.11.25upload
前へ
次へ
ホームページトップへ戻る