V20-MBCエミュレータの開発 その4

ついに!!!

夢にまで出てきた1.2が表示された!!!!

 f:id:PocketGriffon:20200821224828p:plain

難しかった!(TOT)

せっかくなので、どんな感じでデバッグをしていたのかを書いてみたい。

一旦落ち着きたいしね(^^)

 

現象を追え!

最初、おかしな動きに気が付いたのは、ASCIART.BASを読み込んだ後に実行が出来ない事だった。追ってみると、どうやらメモリへのロードは成功しているが、理由は不明だけど実行が出来ないという状態だった。

 

正直、この状態では全くラチが明かず、とにかく症状を絞り込みたい!

あれこれ試してみて、ロード後にキー入力が入る事に気がついた。

それでは…って事で、読んだBASICプログラムをLISTしてみようとしたところ…プログラムの一部が壊れているが分かった。

 

ここで少し原因が絞り込めた。

ASCIIセーブされているASCIART.BASをロード後、BASICの中間コードへ変換する際に失敗しているか、または変換は成功しているがLISTしようと文字列へ戻そうとしている時に失敗しているのか、だ。

実行出来ないのはまた別の事情かも知れないが、それは後回し。

まずは目の前のバグを追い掛ける流れに。

 

ASCIART.BASは大きいので(マシン語レベルの動作を追ってる状態では十分大きい^^;)、もっと小さいプログラムでバグの現象を起こしたい。そしたらこんなパターンが引っかかってきた(先日のブログで載せた写真と同じ)。

f:id:PocketGriffon:20200820100616p:plain

現象をたぐり寄せろ!

MBASIC.CMD自体は起動すると自分自身をメモリの上位へ移動させる。

その後、CS=E8F1h、DS=ES=SS=F000hで実行が開始される。

内部での処理対象となるBASICの1行はF000:0305hに入っていて、ここを読み出すプログラムを追い掛ければ良い事になる。そして出来上がったプログラム(中間言語)はF000:0A34hから格納される。

 

1.5という数字を処理しようとして、整数値[1]から[.]で単精度に変換、次の[5]で倍精度に変換しようとして値を消失させるという、意味不明な動きになっていた。

つまり問題の症状はテキスト→中間コードへの変換途中に起きてる!

 

変数の内部表現はMicrosoft BASICでおなじみの形式だったため、こちらはすんなり理解ができた。PC-8001のBASIC ROMととても良く似ていて、構造的に同じ?と思えた(どちらもマイクロソフト製ですもんね)。

 

この頃、GW-BASICのソースコードが公開された事を思い出した。さっそくソースコードをダウンロードしてみたが…今、目の前にある逆アセンブルリストが、ソースのどこに当たるのかを調べるのが一苦労(^^;; そりゃそうか。

でも特徴的なコードからソースの「どこ」を探ることが出来た。

CP/M-86のMBASIC、MS-DOSのGW-BASIC、細かいところの違いはあったけれども、ソース的にはどうやらほぼ同じという事が判明。これで解析が飛躍的にラクになった!\(^O^)/

 

その後もオーバーフローの算出方法がおかしくなっていたり、パリティの数え方が違っていたり(コード中にパリティで分岐するコードがある)、間違いを直していくけれども完全には直らない。

 

 それにしても今回初めて気が付く8086の仕様もあって驚いた。

・MOVSB/MOVSWでのESはセグメントオーバーライドプリフィックスの影響を受けない

・アドレッシングでBP選択された場合は、SSを採用する

などなど。

意外に根本的なところを理解していない自分に驚いた(^^;;

 

書いたプログラムソースを何度も見直すが間違いがどうしても見つからない。

仕方ないので、上記のアドレス(F000:0305h)をアクセスした瞬間からBASICの中間コードに変換し終えるまでの実行過程を逆アセンブルし、そこに出てくる命令コードを片っ端から見ていく事に。

おそらく問題はフラグを変化させる系の命令に違いない!

 

そしてバグは見つかった!

最終的に決定打となったバグは、XORの被演算子が逆になっていたモノだった!

8086にはdビットと言って、被演算子が逆になるという仕様がある。これを意識してプログラムをしていたんだけど、どうも抜けがあったようだ…。

しかも巧妙にもコメントで「dビットが立っているのでsrc,destが逆になる」と書いていた!!(^^;;; どっかのタイミングで逆にしちゃったのかな…汗

 

イイワケをひとつ。

XORは伝統的?に「XOR AX,AX」という感じに、レジスタに0を入れるコードとして使われるケースが多いため、被演算子の間違いに気づきにくいという事情もあった!

 

ようやく前に進める…

やっと…やっと1.2が表示された!これを見るために3〜4日悩んだ!

1日中取り組んでるわけじゃなかったけれども、常にアタマにあった(^^;;

久しぶりに苦しんだー(T-T)

さあ、ASCIART.BASを動かしちゃうぜ!!

f:id:PocketGriffon:20200822001734p:plain

↑実行するために、実装されてる命令が足りない、というエラー

……orz

 

じ…地道に頑張るよ!!

それではまた次回!(^-^)ノ