10 KERNEL_CS = 0x0008 //カーネル用コード・セグメント
11 KERNEL_DS = 0x0010 //カーネル用データ・セグメント
12 BOOT_CS = 0x0008 //ブートローダ用コード・セグメント(カーネル実行時には、このディスクリプタは削除する。)
15 CR0_PE = 0x00000001 //プロテクト・イネーブル・フラグ
16 //CR0_PG = 0x80000000 //ページング・フラグ
27 * DS, ES, SS には0x10がセットされます。
28 * FS, GS には、0x00がセットされます。
30 .global switchProtectMode
38 1. 割り込みをディスエーブルにする。CLI 命令によってマスク可能ハードウェア割り込み
39 がディスエーブルになる。NMI 割り込みは、外部回路によってディスエーブルにでき
40 る。 (ソフトウェアは、モード切り替えの動作中に例外または割り込みが発生しないよ
49 2. LGDT 命令を実行して、GDTR レジスタに GDT のベースアドレスをロードする。
56 3. 制御レジスタ CR0 の PE フラグ(またオプションで PG フラグ)を設定する MOV CR0
67 4. MOV CR0 命令のすぐ後で、far JMP 命令または far CALL 命令を実行する。 (この操作
68 は通常、命令ストリーム内の次の命令への far ジャンプまたは far コールになる。 )
75 5. MOV CR0 命令の直後に JMP 命令または CALL 命令を実行すると、実行の流れが変化
81 ljmp $0x08, $setCodeSegment
86 6. ページングがイネーブルな場合、 MOV CR0 命令のコードと、 JMP 命令または CALL 命
87 令のコードは、アイデンティティ・マッピングされたページから得たものでなければ
88 ならない(つまり、ジャンプ前のリニアアドレスが、ページングと保護モードがイネー
89 ブルになった後の物理アドレスと同一でなければならない) JMP 命令または CALL 命
91 令のターゲット命令は、アイデンティティ・マッピングされる必要はない。
96 7. ローカル ディスクリプタ テーブルを使用する場合には、 LLDT 命令を実行して LDTR
98 レジスタに LDT のセグメント・セレクタをロードする。
103 8. LTR 命令を実行して、 セグメント・セレクタ付きタスクレジスタを初期保護モード・タ
104 スクへロードする。またはタスクスイッチに関する TSS 情報を保存できるメモリの書
110 9. 保護モードに移行した後、セグメント・レジスタは実アドレスモードで保持していた
111 内容をそのまま保持し続ける。操作手順 4 の JMP 命令または CALL 命令が CS レジス
112 タをリセットする。以下のどれかを実行して、残りのセグメント・レジスタの内容を
114 - DS、SS、ES、FS、GS の各セグメント・レジスタを再ロードする。ES、FS、GS の
115 各レジスタのなかで使用しないものがある場合、そのレジスタにヌルセレクタを
117 - JMP 命令または CALL 命令を新しいタスクに対して実行する。これによって、セグ
118 メント・レジスタの値がリセットされ、新しいコード・セグメントに分岐する。
133 10. LIDT 命令を実行して、IDTR レジスタに保護モード IDT のアドレスとリミットをロー
139 11. STI 命令を実行して、マスク可能ハードウェア割り込みをイネーブルにし、また必要な
140 ハードウェア動作を実行して NMI 割り込みをイネーブルにする。
141 上記の手順 3 と手順 4 の間に他の命令が存在すると、不規則な障害が発生することが
142 ある。システム管理モードで、メモリを参照する命令が手順 3 と手順 4 の間に挿入さ
143 れたときのような状況では、障害は直ちに認識される。