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


16ビットマイコンボードの製作

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
いつか使ってみるつもりで入手してそのまま置いてあった16ビットCPUのことを思い出しました。
AMD社のAM188です。
その名の通り、CPUコアは80188互換の16ビットCPUです。
そのAM188を使った16ビットマイコンボードの製作記事です。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

[第49回]



●8086の最高に悩ましい問題(CSとDS)(その2)

前回からの続きです。
プログラムをROMに書く場合、定数データとか文字列とかもROMに書くのが普通です。
ところが8086の場合、命令コードはCS領域に、そして定数を含む全てのデータはDS領域に置くことになるため、CSとDSで異なる領域を指定した場合には、通常の命令の記述のままでは、CSに置いたデータを参照することはできません。
それを可能にするためには、メモリを参照する命令の直前にセグメント変更プリフィクスCS:を置きます。
前回はそのように対策したサブルーチンを追加することで、理屈の上ではシステムプログラムをROM化しても問題なく走るはず、というところまでプログラム追加を行なったことについて説明をしました。

ここで誤解があるといけませんので補足しておきます。
システムプログラムのROM化はすでに行なっています。
ROMにプログラムがなくては起動することもできませんから、必要最低限のプログラムのROM化は必須です。
実際には段階的に少しずつシステムプログラムをROM化しながら追加を行なってきましたので、前回までのところでは単精度と倍精度の浮動小数点計算プログラムとそのほかの一部のプログラムを除いてはすでにROM化はできています。
残る浮動小数点計算プログラムについて、前回書きましたように悩ましい問題に気が付きましたので、それでセグメント変更プリフィクスを含むサブルーチンを追加して、それをRAM上で動作テストして正しく実行できていることを確認しました。
RAM上では、一応の完成です。
しかし今回のCSとDSの問題はROM化したときに発生する問題なので、たとえRAM上で正しく動いたとしても、それをROMに焼いても正しく動作するということにはなりません。

ROM化しても正しく動作するようにということで、前回書きましたようにそのためのサブルーチンの追加を行なったのですが、私の場合、完璧とは言いがたいのですよねえ。
恥ずかしながら、そのあたりについてはちょいと自信がありません。
おそらく修正オチがある、と思います。
そうなると、ことは厄介です。
ROMに書いてしまっていますから、ブレークポイントを設定してデバッグをするというわけにはいきません。
RAM上でデバッグしたくても、そのプログラムをRAMにロードしてそれを実行すると、CS=DSの状態なので、エラーにはなりません。
ROMで実行したときだけエラーが発生することになりますから、実に厄介です。
ということになりますと。
プログラムリストを目を皿のようにして見ながら、間違っているところを捜すしかありません。
文字通りのデバッグです。
ま、しかし、それは異常が発生したら、の話です。
意外とうまくいってしまうかもしれません。
ということで、RAM上で正常動作を確認したシステムプログラムをROM化して、テストしてみました。

>/load sqrtst1.txt
    10 FOR A=0 TO 10
    20 PRINT "a=";A,"sqr(a)=";SQR(A)
    30 NEXT A
    40 PRINT "end"
data end
>r.
a=0          sqr(a)=0
a=1          sqr(a)=1
a=2          sqr(a)=1.41421
a=3          sqr(a)=1.73205
a=4          sqr(a)=2
a=5          sqr(a)=2.23607
a=6          sqr(a)=2.44949
a=7          sqr(a)=2.64575
a=8          sqr(a)=2.82843
a=9          sqr(a)=3
a=10         sqr(a)=3.16228
end

おお。
SQR()はOKです。
よかった。
ではSID()は?

>/load sidtest.txt
    10 FOR A=0 TO 90 STEP 5
    20 PRINT "a=";A,"sid(a)=";SID(A)
    30 NEXT A
    40 PRINT "end"
data end
>r.
a=0          sid(a)=0
a=5          sid(a)=0.871557E-1
a=10         sid(a)=0.173648
a=15         sid(a)=0.258819
a=20         sid(a)=0.34202
a=25         sid(a)=0.422618
a=30         sid(a)=0.5
a=35         sid(a)=0.573576
a=40         sid(a)=0.642787
a=45         sid(a)=0.707107
a=50         sid(a)=0.766044
a=55         sid(a)=0.819152
a=60         sid(a)=0.866025
a=65         sid(a)=0.906308
a=70         sid(a)=0.939692
a=75         sid(a)=0.965926
a=80         sid(a)=0.984808
a=85         sid(a)=0.996194
a=90         sid(a)=1
end

おお。
これもOKですね。
SID()がよいなら、多分COD()もいいでしょう。

>/load sidtest.txt
    10 FOR A=0 TO 90 STEP 5
    20 PRINT "a=";A,"sid(a)=";SID(A)
    30 NEXT A
    40 PRINT "end"
data end
>    20 PRINT "a=";A,"cod(a)=";cod(A)
>r.
a=0          cod(a)=1
a=5          cod(a)=
ERR: 8 
    20 PRINT "a=";A,"cod(a)=";COD(A)

えっ?
駄目?
SID()はいいけれど、COD()は駄目?
くそっ。
インテルのくそ野郎!
まま。
落ち着いて、落ち着いて。
念のため、TAN()も確認しておきましょう。

>/load tantest.txt
    10 FOR A=0 TO PI/2 STEP PI/36
    20 B=TAN(A)
    30 PRINT "a=";A,"tan(a)=";B
    40 NEXT A
data end
>r.

ERR: 8 
    20 B=TAN(A)

あ。
TAN()はのっけから駄目?
これはひどい。

冗長になりますから、この後の経過は省略しますが、ATN()にもエラーが発生して、そのためのバグ取りも追加して行ないました。
文字通りのしらみつぶしのデバッグを行なった結果、次の2箇所にミスを発見して修正しました。
こちらがbeforeです。

FSI4:MOV SI,*FPI2
CALL FCMPCS   
JS FSI5   
MOV SI,*FPAI   
CALL HLRB


FAT2:MOV SI,*FONE   
CALL FCMPCS   
PUSHF
JS FAT3   
MOV SI,*FONE   
CALL HLRB

こちらがafterです。

FSI4:MOV SI,*FPI2
CALL FCMPCS   
JS FSI5   
MOV SI,*FPAI   
CALL HLRBCS


FAT2:MOV SI,*FONE   
CALL FCMPCS   
PUSHF
JS FAT3   
MOV SI,*FONE   
CALL HLRBCS

以上の作業の結果、COD()やTAN()、ATN()に加えてSIN()、COS()も正しい結果が得られることが確認できました。

しかし。
問題はまだあったのでした。
そう。
とりあえずOKになったのは単精度の浮動小数点計算まで。
ひょっとして、倍精度浮動小数点計算にも同じようなバグがあるのでは?

logfile nd80klog\07022140.txt open

ND80KL/86に接続しました
0001 0047 - z
0003 0339 - 
*** nd80kl/86(am188) basic ****
>/load dsidtst.txt
    10 PRINT "degree,sid,cod"
    20 FOR A#=0 TO 90 STEP 5
    30 PRINT A#,SID(A#),COD(A#),
    40 NEXT A#
data end
>r.
degree,sid,cod
0            0            
ERR: 8 
    30 PRINT A#,SID(A#),COD(A#),

>/exit
0003 037C - 
リモート接続を終了しました
logfile closed at Mon Jul 02 21:45:52 2018

やっぱり、ね。
思わずため息が出てしまいます。
倍精度のSIDなのかCODなのかにバグがあるようです。

こちらについても冗長になりますから途中の経過は省略します。
ため息をつきながら退屈なデバッグ作業を行なった結果、次の2箇所にミスを発見して修正しました。
こちらがbeforeです。

FSID2:MOV SI,*FP180
CALL FMUL


PI:INC DI
MOV SI,*FPAI
JMP AGET

そしてこちらがafterです。

FSID2:MOV SI,*FP180
CALL FMULCS


PI:INC DI
MOV SI,*FPAI
JMP AGETCS

そのように追加でプログラム修正を行なって、あらためてROMに書いて、動作テストをした結果、倍精度の三角関数についても正しく実行できるようになりました。

16ビットマイコンボードの製作[第49回]
2018.7.5upload

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