日立 MB-S1 S1-CP/M80 移植作戦 その22 BIOSの作成6

Last Updated on 2019年10月26日 by kabekin

コンソールI/O関係の不具合原因が分かりました!

何かの参考になるかもしれないのでメモしておきます(何とも凡ミスで恥ずかしい・・・

現象はCP/M起動後、Bdos Err On A: が32回表示された後にa>プロンプトが出たら「^@」が
126個出力されて改行され、停止するまで延々と続く不具合。

この「^@」表示不具合ですが、samさんからコメントを頂いた通りでCONINでNULLを渡していた
ことが原因でした^^

BIOS09からBIOS80に渡しているデータはOKっぽいが、

エコーバックで戻ってくるのは^@
この「^@」という処理はCP/M80内のSHOWITというサブルーチンにあるようです。

;   Output (A) to the screen. If it is a control character
; (other than carriage control), use ^x format.
;
SHOWIT:	LD	A,C
	CALL	CHKCHAR		;check character.
	JP	NC,OUTCON	;not a control, use normal output.
	PUSH	AF
	LD	C,'^'		;for a control character, preceed it with '^'.
	CALL	OUTCHAR
	POP	AF
	OR	'@'		;and then use the letter equivelant.
	LD	C,A
;

詳しくは分かりませんがどうやら文字以外のコードを受取った場合に置き換えられる文字っぽいということが判明。

但し、Bdos Err On A:というBDOSからのメッセージは正常に出力されていることからCONOUTやCP/Mのメッセージ出力部は正常だと思われます。
と、いうわけでBIOS80のコンソールCONSTとCONINを調べてみたところ問題がありました。
今作っているS1用CP/MのBIOSですがZ80とS1の間をコマンドとステータスフラグでやり取りしています。

CONINのやり取りの中でS1からZ80に処理を戻した際に共有メモリをクリアしている部分でやらかしてました^^
CONINサブルーチンはこんな感じで実装していました(ダメな例)

;+++ コンソール インプット(A←入力キャラクタ)
;現在の"CON:"に割当て中のデバイスから1文字入力しアスキーコードをAレジスタにセットしてリターン
;ANKの場合最上位ビットは0でなくてもOK
;入力があるまで内部でループさせる
CONIN:
        ld    A,3             ;BIOS09 CmdNo=3
        ld    (CMDNO),A
        ;BIOS09を呼び出す
        call	REQ09
        call	RES80
        ld    A,(DATAREG)     ;BIOS09から1文字受取り BIOS09でCONINの値を渡すとバッファクリアしているのでループしない
        call  SHREGCLR        ;共有レジスタクリア
        ret

このSHREGCLRサブルーチンですが、BIOS80→BIOS09→BIOS80の一連の処理が終了したときにZ80と6809で共有しているメモリをゼロクリアしているのですが、ここで単純なミス^^

;+++ 共有レジスタクリア
SHREGCLR:
        xor        A
        ld         (CMDNO),A
        ld         (IOSTAT),A
        ld         (DATAREG),A
	ret

CONIN内でBIOS09から受け取ったAレジスタを壊してます^^;;
と、いうわけで^@のエコーバックが戻ってきておりました・・・・
一つ問題解決!!

続いて「^@」が126個表示されて改行が延々と表示される原因
こちらは参考書の注意書きを守っていなかったことによるものでした。
CP/Mの参考書にはCONINは入力があるまでCONIN内でループしなければいけないとの説明があります。

CONSTでデータを確認したらCONINが呼ばれるのではないかと勝手に解釈していたのでBIOS09側に
キー入力データが無くなったらCONSTで$00を返すのでループしなくてもいいだろうと勝手に思っていたのが失敗^^

CONIN内のループは必要です→これ重要^^

2つ目の問題も解決!!
CONINの2点の問題を修正したものがこちら

;+++ コンソール インプット(A←入力キャラクタ)
;現在の"CON:"に割当て中のデバイスから1文字入力しアスキーコードをAレジスタにセットしてリターン
;ANKの場合最上位ビットは0でなくてもOK
;入力があるまで内部でループさせる
CONIN:
        ld      A,3             ;BIOS09 CmdNo=3
        ld      (CMDNO),A
        ;BIOS09を呼び出す
        call    REQ09
        call    RES80
        ld      A,(DATAREG)
        cp      0h              ;入力無しならループさせて抜けない
        jp      Z,CONIN
CONIN1: call    SHREGCLR        ;共有レジスタクリア
        ret
;+++ 共有レジスタクリア
SHREGCLR:
        push    AF
        xor     A
        ld      (CMDNO),A
        ld      (IOSTAT),A
        ld      (DATAREG),A
        pop     AF
        ret

正常に動作するようになりました^^
コンソールI/Oが正常になってキーボード入力とCRT表示ができるようになったので、
DIR してみます^^

おっ!反応がありました。

ディスクI/Oのサブルーチンが実装されていないので、エラーになりますが応答があります^^
DIRとキーインしたときのエコーバックはあったものの改行されずにCPMからの出力があるのでDIRが消えてしまっていますが、キーボードからの指示に対してCCPが応答してCRTに表示される一連の動作は確認できました^^

これでZ80Bカードのハードはほぼ問題なく動作していることも確認できました。

指示に対してCP/M80が応答してくれた、そんな記録・・・

2件のコメント

  1. 問題が解決してよかったですね。
    これでZ80の動作と最小限のI/Oが実現できたのであとはこれをベースに拡張していきましょう。
    Z80からBIOS09の呼び出し処理でREQ09(BIOS09に要求する)とRES80(Z80処理を再開する)は
    自分が提供したソースの名残かと思います。
    おそらくSHREGCLRとRES80はREQ09に統合できるかな?と思っています。最適化してみてはどうでしょうか?
    CP/Mに限らず普通にZ80プログラムを作成する場合の”作法”をなるべく単純にするのがおすすめです。

    1. はい!CONSOLE I/Oは一応動作OKのところまで目途がつきました。
      しかし、DISKIOを実装しないとエラー出まくりで何もできないので、ここからが本番かと思います^^
      今は自分でも分からなくならないように効率など全く考慮されていませんが、ある程度基本的な動作が動くようになったらコードや機能の整理もしたいですね。
      >CP/Mに限らず普通にZ80プログラムを作成する場合の”作法”をなるべく単純にするのがおすすめです。
      そうですね。今のソフトは逐次処理で分岐や繰り返しをしている部分が今風のコーディングでアセンブラ特有の処理を進めながらデータを完成させるような流れにはなっていないと思いますので、このようなコーディングが正しいのかどうか自分では不安です^^;;
      冗長ですが分かりやすいのではないかと自分では満足していたりします・・・(笑

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください