プロテクトモードのセグメント機構

リアルモードとプロテクトモードのセグメント

プロテクトモード時のセグメント機構は、リアルモード時のそれとは大きく異なります。リアルモードの場合、メモリへのアクセス範囲は1MByte(0x00000-0xfffff)に制限されています。またセグメントレジスタには、セグメントアドレスをセットする事によりメモリのアクセスを行います。

一方、プロテクトモードの場合、メモリのアクセス範囲は4GByte(0x00000000-0xffffffff)まで拡張されていて、セグメントレジスタには、メモリのアクセス範囲やアクセス属性が設定された、ディスクリプタ・テーブル[Descriptor Table]のセレクタ値と呼ばれるインデックス値をセットする事によりメモリアクセスが行われます。

リアルモードとプロテクトモードのセグメントの違い
リアルモードとプロテクトモードのセグメントの違い

プロテクトモードのセグメント

セレクタは、セグメントのアドレス・サイズ・属性を格納しておく、ディスクリプタ・テーブル[Descriptor Table]のインデックスとなっていて、CPUはその内容に従い物理メモリーにアクセスを行う。

また、ディスクリプタ・テーブルのアドレスを格納しておくGDTR[Global Descriptor Tbale Register]があり、CPUはこの値を使用して、ディスクリプタ・テーブルにアクセスを行う。

プロテクトモードのセグメント機構
プロテクトモードのセグメント機構

GDTR[Global Descriptor Tbale Register]

アドレス変換を行う時、CPUは任意のメモリ上に存在するディスクリプタ・テーブルを使用するが、これを使用するためには、CPUはあらかじめディスクリプタ・テーブルのアドレスを知っておく必要がある。

GDTRは、このディスクリプタ・テーブルのアドレスを設定するために使用する。このレジスタに、ディスクリプタ・テーブルのリニアアドレスを設定することによりCPUは、ディスクリプタ・テーブルを参照できるようになる。

GDTRの構成
GDTRの構成
GDTRのbit構成
bit 意味 詳細
0-15Table Limit ディスクリプタ・テーブルのLimit値
(テーブルのbyte数-1)がセットされる。
16-47Linear Base Address 使用するディスクリプタ・テーブルのリニア・アドレス

LGDT命令

GDTRに値をロードするためには、6バイトのメモリ上に値をセットしておき、これをLGDT命令によりCPUにロードする。

メモリ上の値は、16bitの範囲(6byteのデータ・オペランドの下位2byte)のLimit値と32bitのベース・アドレス(データ・オペランドの上位4vyte)のLinear Base Addressがレジスタにロードされる。

LGDT
LGDT

セレクタ値

セレクタは、16 ビットのセグメント識別子である。これは、セグメントを直接に指すのではなく、その代わりにセグメントを定義するセグメント・ディスクリプタを指す。

セグメント・セレクタは、次の構成となっている。

セグメント・セレクタの構成
セグメント・セレクタの構成
セグメント・セレクタのbit構成
bit FLAG 意味 詳細
0-1RPL要求特権レベル セレクタの特権レベルを指定する。特権レベルは0 〜 3の範囲が可能であり、0 が最も特権レベルが高い。
これにより、動作レベル(CPL[Current Privilege Level])が高いプログラムでも一時的に、特権レベルを落としてメモリにアクセスする事が可能である。
(CPLが低いプログラムがRPLを高くしてもこれは無効となる)
2TIテーブルインジケータ 使用するディスクリプタ・テーブルを指定する。このフラグをクリアするとGDTが選択され、セットするとLDTが選択される。
3-15Indexインデックス ディスクリプタ・テーブルのインデックス値をセットする。

Segment Descriptor

プロテクトモードでは、セレクタ値をセグメントレジスタにセットする事により、物理アドレスにアクセスするのであるが、CPUはこの時、メモリ上に設定された、Segment Descriptor Tableを参照してアドレス変換を行う。

Segment Descriptorは、セグメントのサイズと位置、およびアクセス制御情報とステータス情報をCPUに提供する。

また、Descriptorには、システム中に1つだけ存在し、全てのプログラムから共通にアクセスするセグメントを定義するGlobal Descriptor Table[GDT]、タスク単位に存在するLocal Descriptor Table[LDT]、割込みの設定に使われるInterrupt Descriptor Table[IDT]がある。

Segment Descriptor Table
Segment Descriptor Table

Segment Descriptorの値

Segment Limit
セグメントのサイズを指定する。
プロセッサは、2つのセグメント・リミット・フィールドを一緒にして20bit値を形成する。プロセッサは、G(グラニュラリティ)flagの設定に応じて、次の2つの方法のうちの1つでセグメント・リミットを解釈する。
  • G Flagが0の時、セグメント・サイズは、1byte単位で、1byteから1Mbyteまでの範囲に及ぶ。
  • G Flagが1の時、セグメント・サイズは、4Kbyte単位で、4Kbyteから4Gbyteまでの範囲に及ぶ。

また、オフセットを設定したセグメント・リミットより大きくすると、一般保護例外(#GP) が発生する。
Base Address
4Gbyteのリニア・アドレス空間内のセグメントにおける、最初の位置を定義する。
Segment Base Addressは、16byte境界にアライメントを合わせなければならない。
16byteの境界にアライメントを合わせることは必須ではないが、プログラムは、コードとデータを16byte境界にアライメントを合わせることによって最大の処理能力を出すことができる。
Type
セグメントまたはゲートのタイプを指示し、セグメントに行うことができるアクセスの種類と伸長の方向を指定する。
セグメント・ディスクリプタのS Flagがセットされていると、ディスクリプタはコード・セグメント用またはデータ・セグメント用である。その場合には、タイプ・フィールドの最上位ビットの状態によって、ディスクリプタがデータ・セグメント用(bit11=0)であるかまたはコード・セグメント用(bit11=1) であるかが決定される。
セグメントまたはゲートタイプ
Type Descriptor 詳細
10進
 
11bit
 
10bit
E
9bit
W
8bit
A
0 0 0 0 0 Data Read Only
1 0 0 0 1 Data Read Only,Access
2 0 0 1 0 Data Read/Write
3 0 0 1 1 Data Read/Write,Access
4 0 1 0 0 Data Read Only,Expand
5 0 1 0 1 Data Read Only,Expands
6 0 1 1 0 Data Read/Write,Expand Down
7 0 1 1 1 Data Read/Write,Expanss
8 1 0 0 0 Code Execution Only
9 1 0 0 1 Code Execution Only,Access
10 1 0 1 0 Code Execution/Read
11 1 0 1 1 Code Execution/Read,A
12 1 1 0 0 Code Execution Only,Expand Down
13 1 1 0 1 Code Execution Only,EAccess
14 1 1 1 0 Code Execution/Read ,
15 1 1 1 1 Code Execution/Read,Expand Down,Access
  • Stack Segmentは、読取り/書込みセグメントでなければならない。Stack Segmentのサイズを動的に変更する必要がある場合には、Stack Segmentをエクスパンドダウン・データ・セグメントにすることができる。
  • アクセス済みビットは、オペレーティング・システムまたはエグゼクティブが最後にこのビットをクリアして以降に、セグメントがアクセスされたかどうかを示す。
S Flag
セグメント・ディスクリプタがシステム・セグメント用(S Flag=0)か、コードまたはデータ・セグメント用(S Flag=1)かを指定する。
DPL Flag
セグメントの特権レベルを指定する。特権レベルは0 〜 3 の範囲で指定でき、0が最高の特権レベルである。DPLは、セグメントへのアクセスの制御に使用される。
P Flag

セグメントがメモリ内に存在しているか(P Flag=1)、または存在していないか(P Flag=0)を示す。


このフラグがクリアされていると、セグメント・ディスクリプタを指しているセグメント・セレクタがセグメント・レジスタにロードされると、プロセッサはセグメント不在例外(#NP)を生成する。


メモリ管理ソフトウェアは、このフラグを使用して、所与の時点でどのセグメントを実際に物理メモリにロードするかを制御することができる。これは、仮想メモリを管理するためのページングに加えた制御を提供する。

D/B Flag

セグメント・ディスクリプタが実行可能なコード・セグメントであるか、エクスパンドダウン・データ・セグメントであるか、またはスタック・セグメントであるかに応じて、異なる機能を実行する。(このフラグは、常に32bitのコード・セグメントとデータ・セグメントに対しては1に設定し、16 bitのコード・セグメントとデータ・セグメントに対しては0に設定する必要がある。)

  • 実行可能なコード・セグメント。
    このフラグは、D Flagといい、セグメント内の命令によって参照される実効アドレスとオペランドのデフォルトの長さを示す。
    このフラグがセットされていると、32bitのアドレスと32bitまたは8bitのオペランドが想定される。クリアされていると、16bitのアドレスと16bitまたは8bitのオペランドが想定される。
    命令プリフィックス66H を使用して、デフォルト以外のオペランド・サイズを選択することができ、プリフィックス67Hを使用して、デフォルト以外のアドレス・サイズを選択することができる。
  • スタック・セグメント(SSレジスタによって指されているデータ・セグメント)。
    このフラグは、B(ビッグ) Flagといい、(push,pop,callなど)暗黙のスタック操作に使用されるスタック・ポインタのサイズを指定する。
    このフラグがセットされていると、32bitのESPレジスタにストアされる32bitのスタック・ポインタが使用される。
    クリアされていると、16bitのSPレジスタにストアされる16bitのスタック・ポインタが使用される。
    スタック・セグメントがエクスパンドダウン・データ・セグメントであるようにセットアップされていると、B Flagはスタック・セグメントの上限も指定する。
  • エクスパンドダウン・データ・セグメント。
    このフラグは、B Flagといい、セグメントの上限を指定する。
    このフラグがセットされていると、上限はFFFFFFFFH(4Gbyte)である。クリアされていると、上限はFFFFH(64Kbyte)である。
G Flag
セグメント・リミット・フィールドのスケーリングを決定する。
G Flagが0の時、セグメント・リミットはbyte単位で解釈される。G Flagが1の時、セグメント・リミットは4Kbyte単位で解釈される。(このフラグは、常にバイト・グラニュラであるベース・アドレスのグラニュラリティには影響を与えない。)
グラニュラリティ・フラグがセットされていると、オフセットをセグメント・リミットに対してチェックするときに、オフセットの下位12bitはテストされない。例えば、グラニュラリティ・フラグがセットされている場合にリミットを0 にすると、有効なオフセットは0から4095 までとなる。
AVL
システム・ソフトウェアで自由に使用することができる。
Last modified: Tue May 20 17:11:35 2008 JST