セグメンテーション、GDT - kentakozuka/yetos GitHub Wiki
- 元々はメモリを区画に分ける意味で付けられた名前
- x86-64 64bitでは本来の機能は無効化され、CPUの動作権限を決める為の機能になっている
セグメント誕生と変遷の歴史
セグメントというのは「部分」だと思ってください。メモリ全体の中の「部分」のことを、セグメントという分け方で考えています。
これを説明するには、現在の Intel x86 プロセッサの始祖である 8086 プロセッサに(さらにその前身たる 8085 まで)遡らねばなりません。
Intel は 8080 プロセッサとそのマイナーアップデートとも言うべき 8085 プロセッサにより、8bit CPU の分野で2強の位置を築きました(対抗としては 6809, あと Intel 互換の Z-80 など)。そして次世代 CPU として、16bit の 8086 の開発を行います。
8086 は 8bit CPU とは違い、メモリ空間が大幅に増強(64KB → 1MB)されました。が、プログラムを作る側としては、8080/8085 からすんなりと移行してもらいたい。そのため、「8080 のアセンブリソースを再アセンブルするだけで 8086 に対応できるようにする」という手段に出ます。
このためにアドレスは 64KB に限定されることになってしまいました。(あくまでも8080/8085 互換ソースの場合) 64KB のアドレッシングで、1MB のメモリ空間を十全に使うためにどうするか。その回答が「セグメント」の導入です。
セグメントという「1MB の中のどの64KB の部分かを示す」ものを追加することで、必要ならば1MBの空間をフルに使いながらも、コードレベルでは64KBのアドレッシングのみで済ませられるようにしたのです。 これを実現したのが 8086 のセグメントレジスタです。
セグメントレジスタは
- コード用(CS)
- データ用(DS)
- スタック用(SS)
- 汎用(ES)
の4個が用意され、これにより「コードとデータの分離」も可能となりました。
さて、16bit CPU が広まっていくと、大型コンピュータにあった特権方式の保護といった高度な(OSに必須な)機能が CPU で実装されるようになってきます。それが 80286 から始まる「プロテクトモード」です。プロテクトモードでは資源を仮想化する(物理と論理を切り離す)ことによる保護が行われるようになっており、Intel は 80286 においてセグメントの定義を変更することでこの仮想化を実現したのです。
プロテクトモードにおいてはセグメントレジスタはメモリアドレスを直接表すのではなく、メモリ空間の情報を格納しているセグメントディスクリプタという領域へのポインタとなっています。 セグメントディスクリプタが「論理アドレス 0x00400000~の1MB」を表していたとして、それが物理的なメモリアドレスのどこに該当するのかは、メモリ管理ユニット(MMU)以外知っている必要がありません。もしかしたら物理メモリが割り当てられていない場合もありえます。 そのような場所にアクセスが発生したら、MMU が割当たっていないことを検知して、新しくメモリを割り当てます。物理メモリに空きがなければ、使う頻度の低い他のセグメントに割り当たっていたメモリを(HDD にデータを退避させるなどして)解放して割り当て直します。(メモリのスワップといわれるものです)
そして32bit CPU になると、わざわざセグメントでメモリ空間を分けずに、32bit のフラットなメモリ空間を一つのセグメントに割り当てる(=フラットメモリモデル)のが常態化します。ここに至ってセグメントの意味は(コードとデータの分離と保護、及びメモリの仮想化の二つ以外)なくなったといってよいのです。
- Global Descriptor Table
- セグメンテーションの設定を集めたもの
- OSが所有するメモリ領域に移動する必要がある
https://teratail.com/questions/223985 https://ascii.jp/elem/000/000/649/649680/