雑記帳
ここはhideyosiの雑記帳です。テケトーに書き散らしてるだけなので間違っていたりとは普通にしてます。信用度は相当低いことをあらかじめご了承を。またご覧のようにWikiを使ってますが、hideyosi意外は書き込めません。

多分合ってないぞ!!!。いま一生懸命勉強中だ! (T∀T))間違ってるとこみつけたら、板にツッコミ入れよう!)

・・・ふっ・・・ 所詮笑われてナンボじゃい!。 (T∀T) 

16bit(8086)のセグメント anchor.png

セグメントとはなんじゃらほい?

8086は16bitですね。内部には沢山のレジスタがありますが、ほぼどれも最大16bitです。

CPUがメモリにアクセスする場合、当然メモリの番地を指定しなくてはなりませんが、そのためのレジスタも16bitです。

ん?おかしいですね?。メモリの番地を指定するためのレジスタも16bit。(16進数で4桁です。)そうなると・・・

0x0000〜0xffff

です。最大0xffffということは、十進数に直すと・・・65,535・・・え? 最大64KB???

そうです。CPUの素直な仕組みで考えると、16bitのCPUは、最大64KBしかメモリをアクセスすることができません。・・・しかし、8086は最大1MBを活用することができるのです。いったいどうやって???

8086CPUは大きなメモリ空間を64KBごとに区切り、各区切りを別の16bitのレジスタで指定することによって、事実上20bit(16進数で5桁)でメモリ番地を指定することができます。この64KBの区切りをセグメントと言います。

メモリ番地を20ビットで表現。これなら、0x00000〜0xFFFFF。つまり、1,048,575バイト。1MBとなる。

具体的には、「セグメントアドレス」+「オフセット値」でアドレスを表現する。

セグメントアドレスもやはり16ビットでしか表現できない。で、それ+何番地ずれているかを表現する。

たとえば、物理的に0x21000番地のメモリにアクセスしたいとする。その場合、レジスタはみな16ビットではあるが、

セグメントアドレスに:0x2000  (セグメントベースという)
オフセットアドレスに:0x1000  (オフセット値という)

とセットすると、

0x2000x16 = 0x20000
               +
             0x1000
--------------------
            0x21000

こう解釈して内部回路に信号を送り、0x21000番地のメモリにアクセスしてくれる。

図にする・・・

物理アドレス
 0x00000   ┌──────┐
          │セグメント  │
           │ (64kb) │  ┌─── ここを読みたい!
 0x10000  ├──────┤  │
          │セグメント  │  │        0x21000とかの指定はできない。
          │      │  │    (だってレジスタが16bitだもん)
 0x20000   ├──────┤  │
           │セグメント  │  │        そこで、セグメントレジスタにセグメント
           │      │←─┘    のベース番地を指定する。(頭4桁だけ)
 0x30000  ├──────┤
          │セグメント  │              0x2000:0x1000 (セグメントベース:アドレス)       
          │      │       これで0x21000にアクセスしてくれる
 0x40000  ├──────┤
    :     │セグメント  │
   :   :      :   
   :   :      :   
 0xE0000  ├──────┤
          │セグメント  │
          │      │
 0xF0000  ├──────┤
          │セグメント  │
          │      │
 0xFFFFF  └──────┘
  (1MB)

※少々乱暴な考え方をすれば、この16bit(8086時)のセグメントはとても変則的で無茶な方法といえるかも。整合性や理屈で考えれば、16bitのまま無理に1MBを使えるようにするより、20bitのCPUを開発するというのが本当といえないか。(もちろんあくまでも後付のお評論家的な話ってことで。)

Page Top

32bit(i386)のセグメント anchor.png

セグメントは元来は、上記の通り16bitでなんとか1MBのメモリを使うための変則的手法だったが、32bitになると使用法や意味合い・存在意義が変化する。

32bit状態になると、BXレジスタ(主にアドレスを指定する)も32bit化してEBXレジスタに変化する。32bitなのだから、0x00000000〜0xffffffffまで。すなわち4GBまで番地を直接指定できる。普通に考えればもうセグメントなど必要ではない。

しかし、32bit状態(i386)のCPUはマルチタスク(いくつものプログラムが平行して動作する)を意識している。そのため、この「セグメント」というメモリ分割管理の仕組みをうまく別の用途に転用することにしたようだ。

まず、GDTという、メモリ分割場所の表を用意する。この表はプログラム(主にOS)で設定する必要がある。GDT表はこんな感じになる。

セグメント番号セグメントの大きさセグメントの開始番地セグメントの属性
01MB0x30000000書き込み禁止
132MB0xA0000000OS専用
27MB0x43880000実行禁止
3512KB0xBA500000OS専用,書き込み禁止
42MB0x90000000特になし
8,1912MB0xCF8600000書き込み禁止

※逆に言えば、GDTを設定しておかないとセグメントが使えない

この状態で、セグメントレジスタに「4」を入れ、EBXレジスタに0x00001111を入れてアクセスしたとする。するとCPUは、

    • えーっと。セグメント番号は4かぁ。
    • じゃ、GDTの4番を見に行こう。ええと、開始番地は0x90000000だね。
    • 大きさは2MBだから、EBXの値も問題ないね。
    • 属性も特に問題はないか。
    • ええと、そうすると、0x90000000+0x00001111だから・・・
    • そうか。物理的な0x90001111番地にアクセスすればいいのか!

と、こう判断して動作を実行する。

特にアプリケーションプログラムなどでは、作る段階では

  • とにかくこのプログラムは、0x00000000番地に読み込まれてスタートするのだ!

という想定で作ればよい。OS側が適切にセグメントをセット&選択してくれるので、上記のような物理アドレスの位置をプログラムが意識しなくてもちゃんと動作してくれる。

Page Top

お勉強中 anchor.png

合ってないと思う。勉強中


Last-modified: 2022-06-14 (Tue) 05:58:05 (GMT) (107d) by