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


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

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

[第30回]



●0 DIVIDE

この2〜3日の作業でかなり機能が充実してきました。
まだ動くのはマシンランゲージのみですが、マシン語ツールとしてはここまでできれば十分実用になります。
実際にシステムプログラムを作り上げていく中でデバッグに随分役立っています。

当初はAM188用のシステムプログラムの作成は適当なところで切り上げておいて、先にKL5C80A12用のシステムプログラムを完成させるつもりでした。
8086用のシステムプログラムを、KL5C80A12版と同時に供給するのは、さすがに無理だろうという至極当然の判断からでした。
でもまあ全然手をつけないでおくわけにもいきませんから、とりあえず入口のあたりだけでもさわっておこうと考えて、AM188用システムプログラムの作成にとりかかったのでした。
しかし、いざ作業を始めてみますと、だんだん面白くなってきました。

おそらく多くの方はZ80や8080のマシン語に比べると8086のマシン語は桁違いに難しい(だろう)、と思われるでしょうけれど。
確かにそういう面もあります。
ありますけれど、ある程度慣れてきますと、それほど難しくはありません。
ひょっとすると8080やZ80のマシン語(アセンブラ)より簡単かもしれません。
ま、それはちょっと言いすぎかもしれませんが。
たとえば。

8080の XCHG はHLレジスタとDEレジスタを交換する命令です。
Z80ニーモニックでは EX DE,HL です。
しかし EX HL,BC とか EX DE,BC はありません。
ところが。
8086の場合はこんな感じです。

2018/6/2  7:226  xchgtest.LST
[00001]                     ;;;XCHG
[00002]                     ;
[00003]                         ORG=8000
[00004] 8000  93                XCHG AX,BX
[00005] 8001  93                XCHG BX,AX
[00006] 8002  91                XCHG AX,CX
[00007] 8003  92                XCHG AX,DX
[00008] 8004  87D9              XCHG BX,CX
[00009] 8006  87DA              XCHG BX,DX
[00010] 8008  87CA              XCHG CX,DX
[00011] 800A  96                XCHG AX,SI
[00012] 800B  87DE              XCHG BX,SI
[00013] 800D  87CE              XCHG CX,SI
[00014] 800F  87D6              XCHG DX,SI
[00015] 8011  97                XCHG DI,AX
[00016] 8012  87FB              XCHG DI,BX
[00017] 8014  873C              XCHG DI,[SI]
[00018] 8016  8715              XCHG DX,[DI]
[00019]                     ;
[00020]                     ;

とても全部は書ききれないので適当にはしょって一部のみアセンブラにかけてみました。
XCHG AX,BX と書いても XCHG BX,AX と書いてもどちらでもOKです。
まこれは8086アセンブラのキャパシティとも言えますが。
XCHG DX,[DI] のようにレジスタとメモリの交換もできます。
いかがでしょうか?
おお、これはひょっとしたら8ビットのマシン語では難しかったプログラムでも楽に書けるのでは?
とお思いになりませんでしょうか?
8086も今では過去のCPUですけれど、今でもWindowsマシンの中で生きています。
コマントプロンプトの中で実行することもできますけれど、それはあくまで仮想8086マシンです。
ここはぜひ本物の8086(AM188は8086上位互換です)を動かしてみてください。
きっと8080やZ80では味わえなかったより大きな感動が得られるに違いありません。

余談になってしまいました。
本題に戻ります。
8086には乗算命令MULと除算命令DIVがあります。
DIVでは0で割るとエラーが発生します。
Fatal error(致命的なエラー)です。
0 DIVIDEの割込みが発生します。
INT 0hの割込みです。
AM188の割込みテーブルは[第22回]で説明しました。

DIV命令を実行する前に除数が0でないことを確認しておくべきですが、プログラムのバグなどで0での除算が実行されてしまうかもしれません。
もしもINT 0hの割込みに対してシステムプログラムが何も対策してなかった場合、そこでシステムはハングアップしてしまいます。
ちょっと作業が進みましたので、この機会に0 DIVIDEエラーをシステムプログラムに組み込みました。
下はテストプログラムです。

2018/5/31  7:226  divtest.LST
[00001]                     ;;;DIV TEST
[00002]                     ;
[00003]                         ORG=8000
[00004] 8000  BA3412            MOV DX,1234
[00005] 8003  B8FFFF            MOV AX,FFFF
[00006] 8006  BB0300            MOV BX,0003
[00007] 8009  F7F3              DIV BX
[00008] 800B  90                NOP
[00009]                     ;END

DIVには16ビット除算と8ビット除算があります。
オペランドに置いた除数のレジスタが16ビットのとき、16ビットの除算が行なわれます。
被除数はDXとAXを連結した32ビットになります。
結果はDXに余りが、AXに商が入れられます。
上のプログラム例(1234FFFF/3)ではオーバーフローかと思ったのですが多分被除数に対して除数が小さすぎるからでしょうか、0 DIVIDEが発生しました。
このプログラムは簡単なテストプログラムとして書きましたので終わりがありません。
このまま実行すると最後に暴走してしまいます。
BPの機能が使えますから、800Bにブレークポイントを設定して実行します。
ブレークすると計算の実行結果を確認することができます。

実行中の様子です。

最初の実行では0 DIVIDE!と表示されました。
次にDX=0000にして実行しました。
0000FFFF/0003=5555です。
今回はエラー表示はありません。
AXレジスタに5555が入っています。
なおどちらもブレークしたように表示されていますが、上の0 DIVIDEの場合にはブレークポイントでのブレークではなくて0 DIVIDE割込みの処理プログラムの中でレジスタダンプをしたものです。
2回目に実行したエラーなしの場合にはPC=800Bですが、1回目のエラー発生時はPC=800Aになっています。
あ。
今気が付きました。この場合にはPC=8009にすべきでした。
あとでプログラムを直しておくことにします。

今度はBX=0000にして実行してみました。

当然0 DIVIDEエラーになりました。
このときも念のためにブレークポイントを800Bに設定してから実行したのですが、次にはブレークポイントを設定しないで実行しました。
同じ結果になりました。
レジスタの表示がブレークポイントの設定によるものではないことの確認です。

説明の途中ですが、ちょっと長くなってしまいましたので、続きは次回にいたします。

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

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