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


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

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

[第7回]


●最初のJMP命令

今回は多くの読者様にとりましては全く意味不明、何を言っているのかわからんぞ、という記述に終始することになるかと思います。
私自身の備忘録を兼ねておりますので、曲げてご了承いただきますようお願いいたします。

前回の終わりのところで、AM188(8086も同じ)のリセット後のスタートアドレスはFFFF0です、と書いたあとで、「どうにも納得できないおかしなことに気が付きました」と書きました。
なにしろ80188(8086)を実際にさわるのはこれが初めてですので、まだしっかり理解できていないところが多々あります。
実は、先日からお見せしております16ビット版TK−80モニタプログラムの最初のスタート部分がおかしい、ということに気が付いたのです。
その最初の部分はこうでした。

[00003]                         ORG=F000

[00053] F000  EB0490        START0:JMP START1 <F006>
[00054] F003  E92301        BRK:JMP BRENT <F129>
[00055]                     ;
[00056] F006  BAA0FF        START1:MOV DX,FFA0;umcs
[00057] F009  B83FE0            MOV AX,E03F;128k,noready
[00058] F00C  EF                OUT DX,AX
   
[00416]                         ORG=FFF0
[00417] FFF0  E90DF0            JMP START0 <F000>

FFF0(物理アドレスのFFFF0)にF000へのJMP命令を書いています。
つい8ビットと同じ感覚でこのように書いてしまいました。
8086では、おそらくはこれは誤りで多分CPUが暴走することになるはずでした。
ところがAM188ではこのように書いても暴走しないで意図した通りの動作をしています。
それで余計に悩んでしまったのでした。
[2017.1.6追記]
上で「暴走しないで」と書いたのは誤りであることがわかりました([第8回]参照)。
[追記ここまで]

どういうことかといいますと。
ちょっとわかりにくいとは思いますが、図で説明します。
下の図はAM188がアクセスできる1MBのメモリマップです。

リセットによってCSにはFFFFがセットされます。
つまりコードセグメントのベースアドレスはFFFF0になります。
セグメントのサイズは64KBですから、リセットによってコードセグメントは物理アドレスの0FFFF0〜10FFEFの範囲になるはずです。
ここからがややこしい話になります。
AM188がアクセスできる物理メモリの上限はFFFFFです。
するとリセット後に実際にアクセスできる実メモリアドレスはFFFF0〜FFFFFのわずか16バイトしかありません。
そういう条件のもとで、問題のプログラムリストのように、F000へのJMP命令を書いた場合、CPUはどこに飛ぶのでしょうか。
8086のJMP命令は相対ジャンプ命令ですから、コードセグメントの中で、つまり論理的な64KBのメモリ空間の中で指定された「相対的な」アドレスにジャンプします。
そこはFFFF0を0000とした場合のF000番地ですから、FFFF0+F000=10EFF0のはずです。
しかしそのアドレスはAM188では存在しないアドレスです。
8086の場合、内部レジスタは20ビットですから、そのアドレスは桁あふれを起こして、その結果として0EFF0にジャンプするのではないか、ということが推測されます。
実際に8086で試してみれば確認できるはずなのですが、手元に8086はありませんし、今のところそこまでする意味はありませんから、それはあくまで推測です。
しかしおそらくそうだろうと考える根拠はあります。
ネツト上で「8086 A20」で検索すると、上記の考えを裏付ける説明がみつかります。

さて、するとなぜAM188ではそのようにならず(つまり0EFF0にジャンプしないで)、コードセグメント外のFF000にジャンプできてしまうのか?という大きな疑問が出てきます。
これにはどうやらAM188のUCS(Upper memory Chip Select)が関係しているらしい、と見当をつけたのですが、AM188のDatasheetを何回も繰り返し読んでもどこにもそのようなことは書いてありません。
UCSは80188のメモリ制御端子で、普通はCPUの外でメモリアドレスからメモリのCS信号を作るところを、内部の特殊レジスタ(UMCS)に値を設定することで、指定した範囲のメモリのCS信号を出力します。
UCSの上限アドレスはFFFFF固定で、下限アドレスはリセット後はF0000になります。

よくはわかりませんが、AM188ではそうなります、ということにしてもよいのですけれど、どうにも気持ちがすっきりしません。
それで納得できないまま、何時間もかけてずっとネットで検索を続けておりましたら、やっと、それらしい記述をみつけました。
ファイル名は「AMD_80186_(1985).PDF」となっていますが、内容からするとどうもIntelの80186ファミリーのデータシートのコピーのようです。
表紙がないので正確なところはわかりません。


[出典]Intel 80186Datasheet?(赤線は筆者)

赤線で囲ったところに問題の答えが書かれているように思います。
ちょっとわかりにくい文章ですが、意訳すると次のようになると思います。
「(CPU内部で算出した)20ビットのアドレスの上位16ビットがUMCSの下位6ビットを0にした値と同じかそれよりも大きいときは、UCSがアクティブになる」
リセット後はUMCSの値(UMCSレジスタの設定値ではなくて上の表に示された値のこと)はF038Hになります。
その下位6ビットを0にした値はF0000Hです。
つまり上の説明を今回の問題にあてはめて解くと、リセット後はCS(コードセグメントレジスタ)の設定値に関係なく、F0000〜FFFFFの範囲のアドレスを指定すると、UCS端子がアクティブになって、その範囲のメモリにアクセスできる、ことになります。

これでやっとすっきりしました。
そういうことでしたら、プログラムリストのままでもよいわけですけれど。
あ。
実際にはCSレジスタには、F000にジャンプしたあと、その少し後ろのところで、F000を設定しています。
下のリストの[00080][00081]の行です。

[00052]                     ;
[00053] F000  EB0490        START0:JMP START1 <F006>
[00054] F003  E92301        BRK:JMP BRENT <F129>
[00055]                     ;
[00056] F006  BAA0FF        START1:MOV DX,FFA0;umcs
[00057] F009  B83FE0            MOV AX,E03F;128k,noready
[00058] F00C  EF                OUT DX,AX
[00059] F00D  BAA2FF            MOV DX,FFA2;lmcs
[00060] F010  B83F1F            MOV AX,1F3F
[00061] F013  EF                OUT DX,AX
[00062] F014  BA70FF            MOV DX,FF70;piomode0
[00063] F017  B80100            MOV AX,0001
[00064] F01A  EF                OUT DX,AX
[00065] F01B  BA72FF            MOV DX,FF72;pdir0
[00066] F01E  B80EFC            MOV AX,FC0E
[00067] F021  EF                OUT DX,AX
[00068] F022  BA78FF            MOV DX,FF78;pdir1
[00069] F025  B8FEFF            MOV AX,FFFE;pacs active
[00070] F028  EF                OUT DX,AX
[00071] F029  BAA8FF            MOV DX,FFA8;mpcs
[00072] F02C  B8B880            MOV AX,80B8
[00073] F02F  EF                OUT DX,AX
[00074] F030  BAA4FF            MOV DX,FFA4;pacs
[00075] F033  B87608            MOV AX,0876;i/o base address=8000
[00076] F036  EF                OUT DX,AX
[00077] F037  BA8380            MOV DX,8083;**** 82c55
[00078] F03A  B080              MOV AL,80;**** all port out
[00079] F03C  EE                OUT DX,AL;****
[00080] F03D  B800F0            MOV AX,F000
[00081] F040  8EC8              MOV CS,AX
[00082]                     ;   MOV AX,CS;
[00083]                     ;   MOV DX,8080;
[00084]                     ;   OUT DX,AX;
[00085]                     ;
[00086]                     ;monitor start
[00087]                     ;  

でも、これでは余りに初心者的でみっともないプログラムですので、少しは、らしいプログラムに直すことにいたします。

本日は時間がなくなってしまいましたので、それについては次回に書くことにいたします。

16ビットマイコンボードの製作[第7回]
2017.1.4upload
2017.1.6追記

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