|
ブートローダその6 セグメント
|
前回までの内容
これまでで、
- CPUは最初リアルモードと呼ばれる16ビットのモードで動作する
- AX、BX、CX、DX、SI、DI、BP、SPという汎用レジスタがあり値を格納することができる
- アセンブラ言語のMOV命令やADD命令で汎用レジスタに値を格納したり演算することができる
- 汎用レジスタは専用の役割を持つことがある
- 汎用レジスタ以外にCS、DS、SS、ES、FS、GSというセグメントレジスタと呼ばれる
16ビットのメモリアクセスに使用する特殊なレジスタがある(最後に少しだけ出てきました)
ということがわかりました。それでは前回の続きでCS、DS、ES、FS、GSレジスタとメモリアクセスについて
セグメントレジスタとメモリアクセス
セグメンテーションという言葉を聞いたことがありますでしょうか?
まさにそのセグメンテーションのセグメントを指定するレジスタがセグメントレジスタになります
セグメント?
セグメントとは、メモリをセグメントと呼ばれるある程度の大きさに区切ったものをいいます
ブートローダの説明で最初に出てきましたセクタは、ディスクを一定の大きさ(512バイト)に区切ったものでした
セクタと同じようにセグメントもメモリを区切ったものの単位だと考えてください
ただしセクタはそのディスクによって大きさが一定で記録される場所も(物理的に記録されているので)一定ですが
セグメントはサイズの上限がありますが、場所を変更したりすることができます
そしてセグメントどうしの領域がお互いかぶさるようにすることもできます
(同時にはセグメントレジスタの数だけしかセグメントはありません。そのかわり自由に変えることができます)
セグメントの指定
このセグメントの開始位置を決めるのがセグメントレジスタCS、DS、SS、ES、FS、GSとなります
セグメントの位置を変えるには前回でてきましたMOV命令が使えます
MOV DS, 0x07C0
上記のようにMOV命令にセグメントレジスタを指定して値を入れてやれば
セグメントの開始位置が変わります
ただし注意していただきたいのがここで入れたDSの値です
なにやら見たことのある値ですが、そうです、これでセグメントの開始位置が0x7C00になります
セグメントの開始位置
セグメントの開始位置はセグメントレジスタで決めるのですが規則があります
セグメントの開始位置=セグメントレジスタに入れた値×16(16進数では0x10)
となります。上記での例でいうとDSに0x07C0を入れたのでDSで指定するセグメントは
DSのセグメントの開始位置=0x07C0×0x10(10進数では16)=0x7C00
と計算でき、DSが指定するセグメントの開始位置は0x7C00となります
これで位置を決めることができました。それでは大きさはどのようになっているのでしょうか?
セグメントの大きさ
CPUは16ビットで動作し、セグメントの開始位置を決めるセグメントレジスタも16ビットでした
同様にセグメントのサイズも16ビットの大きさになりますので0xFFFF(10進数では65535)+1になります
(アドレスは0x0000からはじまりますので+1をしています。時計も0時から始まり23時で合計24時間ですね)
ここまでのおさらいになりますが、16ビットモードでアクセスできる最大のセグメントのアドレスはどうなるのでしょうか
ここでDSに16ビットの最大値0xFFFFを入れた場合を考えてみましょう
その場合セグメントの開始位置は
DSの最大セグメントの開始位置=0xFFFF×0x10=0xFFFF0
となります。そしてセグメントの大きさは16ビット最大値の0xFFFFありますので、
アクセスできる最大アドレス=0xFFFF0(セグメントの開始位置)+0xFFFF(セグメントの大きさ)=0x10FFEF
となります。図でみると
となります。1MB(1024×1024=1048576バイト)を16進数で表すと0x100000となります
16ビットのリアルモードでは最大0x10FFEFまでのアドレスにアクセスできますので
(実際にはアドレスバスの都合上0x000FFFFまでのアクセスに制限されます)
だいたい1MBぐらいまでのメモリにアクセスできることになります
次回はセグメントにアクセスする方法についてです