保護モードとは何ですか?

OSを作成するには、多くの詳細を理解する必要があります。 それでは、少しあなたに啓発させてください(しかし、あなたがマナを自分で読んで、話をすることに同意することにしましょう)。
正直なところ、ネットワークの広大さの中でPMには大量の脂肪質の素材があり、 ileypehatはこのモードについて少し話しましたが、とにかく一般的なフレームワークでそれを説明するように頼まれました。 次に、理論を簡単に説明します(一般的に、Intelはこのために特別にマナを書きました)。次に、コードの記述を開始します。


プロテクトモードの概要。
したがって、PMはDOSのリアルモード(RM)以降、通常のすべてとは大きく異なります。 慣れる必要があります。64キロバイトの静的セグメント、1キロバイトの割り込みテーブル、セグメントレジスタのデータベースベースのアドレスなど、まったく新しい世界です。
セグメントは現在、 グローバル記述子テーブル(GDT)に記述されています。 このテーブルは、1つのコピーにのみ含めることができます。 彼女は心の構造です。 セグメントではありません! メモリ内のどこにでも配置できますが、アドレスと制限はGDTRレジスタに記録されます。 その構造は次のとおりです。

画像

テーブル自体は、次の構造のエントリで構成されています(ところで、nullエントリは空です。これは重要です。null記述子で「記述」されたメモリにアクセスする場合、#GP-General Protection Faultを取得します)
この構造を詳しく見てみましょう。
画像

1.セグメント制限:
このフィールドの目的は名前で明確ですが、微妙です。 犬はビットG(粒状性)に埋もれています。
インストールされていない場合、メモリはバイト単位で「カウント」されます。 この場合、セグメントサイズは、1バイトのサイズごとに1バイトから1メガバイトまで変化します。
1に設定すると、ページングメモリが入力されます。 次に、4キロバイト(ページサイズ)にサイズを変更して、4キロバイトから4ギガバイトのRAMをアドレス指定できます。 一般に、ページのアドレス指定が推奨されます((1MB + 64Kb-16byte)と4GBを比較してください)。 この投稿では、セグメント化されたアドレス指定についてのみ説明しましょう。 ページングについては、別の議論に値します。

2.ベースアドレス:
ここでは、データベースの物理アドレスを示します。

3.タイプフィールド:
ビットの組み合わせにより、セグメントのタイプが決まります。
画像

4. S(記述子タイプ):
Intelのドキュメントには、このビットが設定されていない場合、この記述子はシステムセグメント用であり、そうでない場合はコードまたはデータであると書かれています。 システムとは、LDT、TSS、割り込みゲート、およびそれらのような他のものを意味します(それらについては後で)。

5. DPL(記述子特権レベル):
説明されたセグメントの特権。 誰もがリングを知っています。

6. P(セグメントが存在する):
このビットが設定されている場合、プロセッサはセグメントが既にメモリ内にあることを「認識」します(ただし、有効と言う方が良いです)。 未定義のPビットを持つ記述子セレクターをセグメントレジスタにロードすると、#NP(存在しない)例外が発生します。 一般に、この華やかなフレーズの意味については少し後で説明します。

7. D / B:
異なるタイプのセグメントでは、解釈が異なります。
1.コードセグメントの場合:
32または16ビットの有効なアドレス長とオペランドサイズ。
(1-32; 0-16);
2.スタックの場合:
スタックポインターは32ビットまたは16ビットです。 (1-32; 0-16);

8. G:
セグメント制限が測定される単位(バイト、ページ)に影響します。 一般に、CR0レジスタの31ビットを設定することにより、PMに切り替えるときにページングを有効にできます。

詳細情報:
グローバルという言葉は無駄ではなかったと思います。 そのため、まだ何らかの種類のタブレットがあります。 確かに、 ローカル記述子テーブルもあります。 非常に多くの可能性があります。 たとえば、タスクの実装などに使用できます。 しかし、 LDTはすでにセグメントです! 「ローカル記述子プレートのセグメント記述子」のようなフレーズに慣れてください。

テーブルについて説明した後、テーブルをGDTRレジスタにロードする必要があります。 これはmovにはほど遠い。 GDTRには lgdt fwordコマンド(値) 入力されます 。 つまり、この構造を独立して形成し、前述のレジスタにロードする必要があります。 このレジスターで作業しているチームはまだありますが、ヨーロッパ中を駆け巡っています。

別のポイント。 PMでは、セグメントレジスタはセグメントのベースアドレス(RMなど)ではなく、 セレクターと呼ばれる特別にトレーニングされたピースを格納します。 その構造は次のとおりです。
画像
ここで、インデックスはテーブル内の記述子のシリアル番号です。
TIは、記述子を探す場所を示します( GDTまたはLDTで )。

テーブルの作成方法がすでに明確になったので、PMに切り替える方法について説明します(これはRMからのみ実行できることに注意してください)。 一般的には、CR0制御レジスタのビット0を設定するだけです。 私は嘘をついていますが。 まず、すべての割り込み( NMIマスク不可割り込みを含む)を含む)を禁止し、 A20アドレス行を開いて(32ビットのアドレス指定が可能になるように)、 GDTRを読み込み、開始マークにジャンプする必要があります。

ブートローダー(KOLIBRI'skyを使用できます)を使用して、アドレス1000h:0(RM'ovsky、アドレスをメモします)でコードをロードします。
ブートローダーから直接PMに切り替えると、それらの人ほどスムーズではありません。 すべてが少し複雑です。 しかし、最初に、ブートローダーがロードするコードを見てみましょう(すべてFASMに記述します)。 これは一種のhelloworldです。 起動し、PMに移動して挨拶を印刷します。 それだけです

format binary
xor ax,ax
cli ;
mov ss,ax
xor sp,sp
sti
mov ax,3
int 10h

jmp 1000h:r_start

r_start:

mov ax,1000h;
mov ds,ax
mov es,ax

in al, 0x92; A20
or al, 2
out 0x92, al

cli ;
mov al,8Fh; NMI
out 70h,al
in al,71h

lgdt fword [GDTR]; GDTR
mov eax,cr0
or al,1; 0-
mov cr0,eax; PM

jmp fword 08h:Startup32; PM

align 8 ;
GDT:
dq 0 ;
db 0FFh,0FFh,0,0,0,9Ah,0CFh,0 ;
db 0FFh,0FFh,0,0,0,92h,0CFh,0;
db 0FFh,0FFh,0,80h,0Bh,92h,40h,0 ;
label GDT_SIZE at $-GDT
GDTR:
dw GDT_SIZE-1
dd GDT+10000h
; 32- . 1000h, 1000h*10h ( ; ) => GDTR (!) = 10000h ( )+offset

virtual ;, ,
rb 10000h-$;
end virtual
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;PM32 Entry;;;;;;;;;;;;;;;;;;;
use32
org $+10000h; : PM Flat-, ; PM org', ; Flat . .

Startup32: ; PM
mov ax,10h ; . (!
mov es,ax ;) - 08h. - 10h, - 18h
mov ds,ax
mov fs,ax
mov ss,ax
mov esp,10000h;
mov ax,18h
mov gs,ax

mov esi,hi_string ;,
call print
jmp $

;ESI -
print:
pushad
xor ebx,ebx
mov ah,07h;
puts:
mov al,[esi+ebx]
mov [gs:(ebx*2)],ax
inc ebx
test al,al
jnz puts
popad
ret
hi_string db 'Welcome to PM, dude',0


私たちは何をしましたか? ブートローダーは1000h:0で正常にロードし、そこから実行を継続しました。 まず、 A20をオンにし、すべての割り込みを禁止し、適切な値をGDTRにロードして、入力ラベルにジャンプしました。 飛びついたことに気づいた
jmp fword 08h:Startup32
つまり、08hはコード記述子セレクターです。 それに慣れてください。

次に、この奇跡を開始する方法。 個人的には、WinImageとVirtualBoxを使用しています。 ブートローダーをディスケットのブートセクターにプッシュし、.binファイルをルートに配置します。 .vfdに保存し、仮想マシンのプロパティにディスクイメージへのパスを書き込み、起動して結果を確認します。

次の号では、割り込み、フォールト、トラップ、アボート、およびそれらの動作、キャッチ、デバッグについて検討します。 アーキテクチャについて話を始めましょう。

情報源。
1)真の道を指摘し、最初に私を助けてくれたPhantom_84別名エゴに感謝したい。 それがなければ、私がそれを理解するのははるかに難しいでしょう。
2) BrokenSword'aの記事BrokenSword'aの記事。 彼らは注意を払う価値があります。
3) Intelシステムプログラミングガイド

Source: https://habr.com/ru/post/J118881/


All Articles