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


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

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

[第5回]


●セグメントおよびセグメントレジスタ

8086は16ビットCPUですが8080の影響を色濃く残しています。
あるいはIntelが意図的にそのように8086を設計したのかもしれません。
8080のプログラミングについてある程度以上慣れた人でしたら、8086のプログラミングは割と楽に習得できると思います。
ただ一定規模を超える8086のプログラムを組もうとすると、あるいはセグメントの概念が障害になるかも知れません。

8086は16ビットのCPUで、アドレスラインはA0〜A19の20本あります。
ハード的に見れば1024KB(1MB)のメモリを直接接続することができます。
しかしソフトの側から見ると、実は連続したメモリアドレスとしては8080やZ80と同じように64KBのメモリ空間をアクセスすることしかできません。

8080ではメモリアドレスを主に示すレジスタとしてHLレジスタを使います。
8080は8ビットのCPUなのですが、Aレジスタ以外は、2つをつないでHL、DE、BCとすることで16ビットのレジスタとして使うことができます。
この16ビットのレジスタにメモリアドレスを入れることで8ビットのCPUでありながら64KBのメモリ空間をアクセスすることができます。

8086にはHL、DE、BCレジスタと同様なレジスタとして、AX、BX、CX、DXの4個の16ビットのレジスタがあって、それぞれはAH、AL、BH、BL、CH、CL、DH、DLのように8ビットのレジスタとしても使うことができます。
そのほかに8ビットに分けられない16ビットのSI、DIやBPといったレジスタもあります。
これはZ80のIX、IYレジスタに近い使い方のレジスタです。
ここで注目したいのは、8086でもそのレジスタはいずれも16ビットということです。
つまりレジスタを使ってメモリをアクセスしようとすると、16ビットCPUなのに8080やZ80と同じように64KBのメモリ空間しかアクセスできません(レジスタを使わないで直接アドレスを指定する場合でもやっぱり16ビットのアドレスしか指定できません)
[2017.1.3注記]
昨晩は時間がなくて走り書きになってしまったなかで、レジスタが16ビットであることを強調する余りに、ついうっかりして舌足らずなことを書いてしまいました。
CALL命令、JMP命令でジャンプ先を直接指定する場合には、アドレス部が24ビットのfar CALL、far JMP命令がありますので、その場合には1MBのメモリ空間のどこでも直接指定することができます。
この場合でも厳密にいえば、オペランド部は24ビットのアドレスを示すのではなくて、16ビットのアドレス+16ビットのセグメント値の組み合わせになります。
セグメントについてはこれから説明をします。
[注記ここまで]

川崎製鉄のKL5C80A12はその制約の中で64KBを越えるメモリ空間をアクセスするために、MMUの助けを借りてバンク切換えの方法でそれを実現しています。
8086はメモリバンクの窓を64KBいっぱいに広げたセグメントという概念を取り入れ、それを扱うためにCS、DS、ES、SSという16ビットのレジスタを用意しました。
このレジスタも16ビットです。
16ビットのレジスタを使って、それを越える20ビットのメモリアドレスを示すために、初心者には理解しにくいものになっていますが、これはやむを得ないことでしょう。

セグメントというのはその下限アドレス(ベースアドレス)がA19〜A4の16ビットで示されA3〜A0の4ビットが0000であるような64KBのメモリ空間のことをいいます。
たとえば00000〜0FFFFは下限アドレスをA19〜A4の上位16ビットで示したときに0000であるセグメントです。
00010〜1000Fは下限アドレスの上位16ビットが0001のセグメントです。
また00020〜1001Fは下限アドレスの上位16ビットが0002のセグメントです。
このようにメモリバンクの窓を64KBの枠一杯に広げたものがセグメントです。
そしてその16ビットのベースアドレス値を保持するためのレジスタがセグメントレジスタです。

KL5C80A12はMMUによるバンク切換えを使って64KBを越えるメモリにアクセスできますが、その窓のサイズの合計は64KBを越えることはできません。
たとえば同時にROMとRAMにアクセスできるようにした場合、ROMの窓とRAMの窓のサイズの合計は最大64KBです。
これに対して8086は4本あるセグメントレジスタを使って相互に重なりのないメモリ空間(セグメント)を指定することによって直接アクセスできるメモリ空間を最大で64KB×4=256KBに広げることができます。

まだ経験の浅いプログラマの負担を軽減するためでしょうか、小規模なプログラム(一般的なプログラムはそうであることが多いはずです)を書くときに、セグメントを意識しなくてもよいような配慮がなされています。
8086のセグメントにはあらかじめ用途が決められています。
コードセグメントはプログラム命令コードがあるメモリ範囲を示すセグメントで、そのベースレジスタはCS(Code Segment register)です。
データセグメントはデータを入れるためのメモリ範囲を示すセグメントで、そのベースレジスタはDS(Data Segment register)です。
スタックセグメントはスタックのためのメモリ範囲を示すセグメントで、そのベースレジスタはSS(Stack Segment register)です。
このほかにエクストラセグメントというフリーのセグメントが指定可能で、これはたとえば大量のデータのブロック転送などのように2つのデータセグメントを定義できるとありがたいようなときの予備として使えるセグメントで、そのベースレジスタはES(Extra Segment register)です。

この仕組みによって、あらかじめCSにプログラムROM領域を、DSにRAM領域を設定しておけば、あとはセグメントの存在は意識せずに、たとえば
MOV [BX],AL
などのような命令を書いて、普通に実行させることができます。

上の命令は8080の
MOV M,A
Z80の
LD (HL),A
に相当する命令です。

本日は時間がなくなってしまいました。
次回に続きます。

16ビットマイコンボードの製作[第5回]
2017.1.2upload
2017.1.3注記

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