GDT、LDT、GDTR、LDTRの詳細
Gdt Ldt Gdtr Ldtr Detailed
reference http://blog.csdn.net/u013982161/article/details/52138155
1.はじめに
プロテクトモードのセグメントレジスタは、16ビットセレクタと64ビットセグメント記述子レジスタで構成されています。
セグメント記述子レジスタ:セグメント記述子を格納します
セレクター:ストレージセグメント記述子のインデックス
PS:元のリアルモードの各セグメントレジスタは、プロテクトモードのセグメントセレクタとして使用されます。 80486には6つ(つまり、CS、SS、DS、ES、FS、GS)の80ビットセグメントレジスタがあります。セレクタCSに対応するセグメントはコードセグメントのままであり、セレクタSSに対応するセグメントはまだスタックセグメント。
2.詳細
1.グローバルディスクリプタテーブルGDT(グローバルディスクリプタテーブル)
グローバルディスクリプタテーブルGDT(セグメント)はメモリに格納され、レジスタGDTRはGDTのエントリを格納します。
グローバルディスクリプタテーブルGDTは1つだけです( 1つのプロセッサが1つのGDTに対応します )、GDTはメモリ内のどこにでも配置できますが、CPUはGDTのエントリ、つまりベースアドレスが配置されている場所を認識している必要があり、Intelは レジスタGDTRは、GDTエントリアドレスを格納するために使用されます プログラマがGDTをメモリ内の特定の場所に設定した後、LGDT命令を介してGDTエントリアドレスをこのレジスタにロードできます。それ以降、CPUはこのレジスタの内容に従ってGDTエントリとしてGDTにアクセスします。 GDTRは、GDTのベースアドレスとそのテーブル長の制限をメモリに格納します。
ベースアドレスは、GDTテーブルのバイト0が 線形アドレス空間 テーブル長のアドレスは、GDTテーブルのバイト長値を示します。
GDTRグローバル記述子レジスタ:48ビット、上位32ビットはGDTベースアドレスを格納し、下位16ビットはGDT制限長を格納します。
LGDTおよびSGDT命令は、それぞれGDTRレジスタの内容をロードおよび保存するために使用されます。マシンの電源がオンになるか、プロセッサがリセットされると、ベースアドレスはデフォルトで0に設定され、長さの値は0xFFFFに設定されます。保護モードの初期化プロセス中に、GDTRに新しい値をロードする必要があります。
2.セグメントセレクター(セレクター)
セグメントレジスタは、セグメントセレクタを格納します。
GDTRによるグローバルディスクリプタテーブルへのアクセスは、「セグメントセレクタ」(リアルモードのセグメントレジスタ)を介して行われます。セグメントセレクタは16ビットレジスタです(リアルモードのセグメントレジスタと同じ)
セグメントセレクタには、記述子インデックス(インデックス)、TI、および要求された特権レベル(RPL)の3つの部分が含まれます。
-
インデックス(記述子インデックス)の部分は、何が必要かを示します 記述子テーブル内のセグメント記述子の位置 この場所から、GDTRに格納されている記述子テーブルのベースアドレスに基づいて、対応する記述子を見つけることができます。次に、記述子テーブルのセグメントベースアドレスと論理アドレスのOFFSET(SEL:OFFSET)を使用して、線形アドレスに変換します。
-
セグメントセレクタのTI値にはビット0または1が1つだけあります。0はセレクタがGDTで選択されていることを意味し、1はセレクタがLDTで選択されていることを意味します。
-
要求された特権レベル(RPL)はセレクターの特権レベルを表し、4つの特権レベル(レベル0、レベル1、レベル2、およびレベル3)があります。
特権レベルに関する注意:タスクの各セグメントには特定のレベルがあります。プログラムが特定のセグメントにアクセスしようとすると、プログラムが所有する特権レベルとアクセスする特権レベルを比較して、そのセグメントにアクセスできるかどうかを判断します。システムは、CPUが同じ特権レベルまたはそれより低い特権レベルのセグメントにのみアクセスできることを規定しています。
たとえば、論理アドレスが与えられた場合:21h:12345678hは線形アドレスに変換されます
a。セレクターSEL = 21h = 0000000000100 0 01bこれは、セレクターのインデックス= 4、つまり100bがGDTの4番目の記述子を選択することを意味します。TI= 0は、セレクターが左側のGDT01bで選択されることを意味します。特権レベルRPL = 1を表します。
b。 OFFSET = 12345678hこの時点でGDTの4番目の記述子に記述されているセグメントベースアドレス(Base)が11111111hの場合、線形アドレス= 111111111h + 12345678h = 23456789h
3.セグメント記述子(セグメント記述子)
8バイトと64ビット、各セグメントには対応する記述子があります。
記述子記述子によって記述されるさまざまなオブジェクトに応じて、記述子は、ストレージセグメント記述子、システムセグメント記述子、およびゲート記述子(制御記述子)の3つのカテゴリに分類できます。セグメントのベースアドレス、長さ制限、およびアクセス内部タイプの属性は、記述子で定義されます。ベースアドレスはセグメントの基本アドレスを示します。これは線形アドレスを形成するために使用され、制限長はセグメントの長さを表し、ストレージスペース保護に使用されます。セグメント属性はセグメントのアクセス権と現在の存在を表します。メモリ内のセグメントおよびセグメントの特権レベル。
4.ローカルディスクリプタテーブルLDT(ローカルディスクリプタテーブル)
ローカルディスクリプタテーブルLDT(セグメント)はメモリに保存され、これを説明します ディスクリプタ GDT(これもメモリ)に格納され、この記述子に対応するセレクタはレジスタLDTRに格納されます。
タスクごとに1つずつ、複数のローカル記述子テーブルが存在する場合があります。 GDTとLDTは、次のように理解できます。GDTは第1レベルの記述子テーブルであり、LDTは第2レベルの記述子テーブルです。示されているように
LDTとGDTは、LDTがGDTにネストされていることを除いて、基本的に同じです。 LDT自体もメモリのセグメントであり、セグメントであるため、LDT自体にもそれを説明する記述子があります。この記述子はGDTに格納されており、この記述子に対応するセレクターがあります。 LDTRはそのようなセレクターをロードします。 LDTRは、ローカル記述子テーブルの開始位置を記録します。 GDTRとは異なり、LDTRのコンテンツはセグメントセレクターです。
LDTRローカル記述子レジスタ:16ビット、上位13はGDTのLDTのインデックス値です。
LDTRは、lldt命令を使用して、プログラム内でいつでも変更できます。上の図に示すように、セレクター2がロードされている場合、LDTRはテーブルLDT2を指します。
例:テーブルLDT2の3番目の記述子によって記述されたセグメントのアドレス12345678hを選択する場合。
-
まず、LDTRをロードしてLDT2を指すようにする必要があります。コマンドlldtを使用して、Select2をLDTRにロードします。
-
論理アドレス(SEL:OFFSET)を介してアクセスする場合、SEL = 3のインデックスは、3番目の記述子が選択されることを意味します。TI= 1は、セレクターがLDTで選択されることを意味します。このとき、LDTRはLDT2を指すため、LDT2で選択されます。 SEL値が1Chの場合(バイナリは11 1 00b)。オフセット= 12345678h。論理アドレスは1C:12345678hです。
-
記述子はSELによって選択され、線形アドレスは記述子のベースアドレスにOFFSETを追加することによって取得できます。たとえば、ベースアドレスが11111111hの場合、線形アドレス= 111111111h + 12345678h = 23456789h
-
この時点で、LDT1の3番目の記述子にアクセスする場合は、lldt命令を使用してセレクター1をロードし、手順2と3を実行します(LDTRがLDT1を再度指すため)
各プロセスには独自のプログラムセグメント、データセグメント、およびスタックセグメントのセットがあり、ローカル記述子テーブルを使用するため、各プロセスのプログラムセグメント、データセグメント、およびスタックセグメントを一緒にパッケージ化でき、LDTRを変更することで実現できます。さまざまなプロセスのセグメントへのアクセス。
タスクが切り替わると、プロセッサは新しいタスクのLDTを変更します セグメントセレクター また、セグメント記述子は自動的にLDTRにロードされます。マシンの電源がオンになるか、プロセッサがリセットされると、セグメントセレクタとベースアドレスはデフォルトで0に設定され、セグメント長は0xFFFFに設定されます。
3つの例
1.GDTにアクセスします
TI = 0の場合、上の図に示すように、セグメント記述子がGDTにあることを意味します。
①最初にGDTRレジスタからGDTベースアドレスを取得します。
②次に、GDTのセグメントセレクタの上位13ビットのインデックス値を持つセグメント記述子を取得します。
③セグメント記述子には、ベースアドレス、制限長、セグメントの優先度などのさまざまな属性が含まれており、セグメントの開始アドレス(ベースアドレス)を取得し、オフセットアドレスyyyyyyyyをベースアドレスに追加して最終的な線形を取得します。住所。
2.LDTにアクセスします
TI = 1の場合、上の図に示すように、セグメント記述子がLDTにあることを意味します。
①最初にGDTRレジスタからGDTベースアドレスを取得します。
②LDTRレジスタ(LDTR上位13ビット)からLDTが配置されているセグメントの位置インデックスを取得します。
③この位置インデックスを使用してGDTのLDTセグメント記述子を取得し、LDTセグメントのベースアドレスを取得します。
④セグメントセレクタの上位13ビットの位置インデックス値を使用して、LDTセグメントからセグメント記述子を取得します。
⑤セグメント記述子には、セグメントのベースアドレス、長さ制限、優先度、およびその他の属性が含まれています。これにより、セグメントの開始アドレス(ベースアドレス)が取得され、オフセットアドレスyyyyyyyyがベースアドレスに追加されて、最終的な線形アドレスが取得されます。
4、拡張
GDTRとLDTRに加えて、IDTRとTRがあります
1.割り込みディスクリプタテーブルレジスタIDTR
GDTRの役割と同様に、IDTRレジスタは、割り込み記述子テーブルIDTの32ビットの線形ベースアドレスと16ビットのテーブル長の値を格納するために使用されます。命令LIDTおよびSIDTは、それぞれIDTRレジスタの内容をロードおよび保存するために使用されます。マシンの電源がオンになるか、プロセッサがリセットされると、ベースアドレスはデフォルトで0に設定され、長さの値は0xFFFFに設定されます。
2.タスクレジスタTR
TRは、特別なタスク状態セグメント(TaskStateセグメント、TSS)をアドレス指定するために使用されます。 TSSには、現在実行されているタスクに関する重要な情報が含まれています。
TRレジスタは、現在のタスクTSSセグメントの16ビットセグメントセレクタ、32ビットベースアドレス、16ビットセグメント長、および記述子属性値を格納するために使用されます。これは、GDTテーブルのTSSタイプ記述子を参照します。命令LTRおよびSTRは、それぞれTRレジスタのセグメントセレクタ部分をロードおよび保存するために使用されます。 LTR命令を使用してセレクタをタスクレジスタにロードすると、TSS記述子のセグメントベースアドレス、セグメント制限長、および記述子属性がタスクレジスタに自動的にロードされます。タスク切り替えを実行すると、プロセッサは新しいタスクのTSSのセグメントセレクタとセグメント記述子をタスクレジスタTRに自動的にロードします。