プロテクティッドモードとGDT前回までの内容これまでで、リアルモードで使用できるメモリマップから0x00000500から0x000A0000が未使用領域メモリマップを見ると、リアルモードでは読み込めるファイルのサイズに限界がある(638kバイト)大きなサイズのカーネルを読み込むには32ビットで動作するプロテクティッドモードで読み込む必要がある1段階目のブートローダは512バイトと小さいため、2段階目のブートローダを作る必要がある一般的なOSは0x00100000にカーネルがロードされるということがわかりました。それではカーネルローダの開発を進めていきましょう!前回までで、カーネルローダに移行することができました今回は主に32ビットで動作するプロテクティッドモードについて見ていきます最初は32ビットのレジスタについて説明します32ビットレジスタ今までは16ビットのレジスタのみを紹介してきました(EFLAGSレジスタは32ビットでした)32ビットのプロテクティッドモードにする前に、32ビットのレジスタについて紹介します16ビットの汎用レジスタAX、BX、CX、DX、BP、SI、DI、SPは拡張されて(Extended)それぞくれEAX、EBX、ECX、EDX、EBP、ESI、EDI、ESPの名前で32ビットのレジスタとして使用できます。Mode)は仮想メモリが扱えますので、その名前の通り”保護モード”と言えます。プロテクティッドモードの特徴として32ビットで動作する仮想メモリ(ページング)が使用できる仮想メモリを扱うため、メモリを扱う方法がリアルモードから変わる32ビットで動作するためメモリを4GBまで使用することができるBIOSの処理が使用できなくなるなどがあります。Table)を使ったメモリアクセスを行う準備をします。次のプロテクティッドモードをONするにはCPUの特殊なレジスタであるコントロールレジスタCR0の設定を行いますそして、4GBののメモリ空間を利用するにはCPUのアドレスバスを使用出来るようにキーボードコントローラから設定しますまたまた、いきなり難易度が急上昇しました。難しい語句がいきなりでてきて何のことやらさっぱりです。難しいので、順番に詳細を見ていきたいと思います。Table)リアルモードではコードセグメントCS、データセグメントDS、FS、ES、スタックセグメントSSと各セグメントに対応したオフセットを使ってメモリアクセスしていました。Table)GDTを日本語で言うと”大域的記述子表”といったところでしょうか。日本語にするとますます難しい。Descriptor)といい、セグメントの開始位置、セグメントのサイズアクセス権限の設定などを細かく設定できますこのセグメントディスクリプタは全部で8192個まで持つことができますプロテクティッドモードでは仮想メモリとしてセグメンテーションが扱えるようにGDTが作られています。逆にGDTを巧みに駆使することでセグメンテーションを行いますLinuxなどのOSは仮想メモリとしてセグメンテーションではなく管理が比較的楽なページングを使っていますが、パソコンについてはCPUの仕様上セグメンテーションの設定を行う必要があります。必要ありますが、Linuxでは4GBのメモリ空間全部を1つのセグメントとしてみなしてGDTの設定をしています。このホームページでもその方針でいきますGDTとセグメントレジスタの役割GDTはセグメントディスクリプタのテーブルで、各セグメントディスクリプタはメモリ上のセグメントに対応していますその対応したセグメントの開始位置、サイズ、アクセス権限の設定をGDTのセグメントディスクリプタで行うことができますリアルモードでは各セグメントの開始位置はCS、DS、ES、GS、FS、SSで決定していましたが、このようにプロテクティッドモードではGDTのセグメントディスクリプタで決定するためリアルモードで使用していたCS、DS、ES、FS、GS、SSは違う役割となりますプロテクティッドモードのセグメントレジスタCS、DS、ES、FS、GS、SSの役割はGDTの何番目のセグメントディスクリプタを使用するかを決めます図で見て行きましょうこのようにセグメントレジスタはGDTのセグメントディスクリプタの何番目を使用するのかを決めます何番目かを指定するときにはセグメントディスクリプタのオフセット番号を指定します例えば図のCSは1番目(最初を0番目として)を指していますセグメントディスクリプタのサイズは64ビットで8バイトですので、1番目のセグメントディスクリプタの開始位置は8バイト目となります。CSは0x08を入れると1番目のセグメントディスクリプタを指すことになります同様にDSには0x10が入っています。Address)でした。論理アドレスのセグメントレジスタに格納されているセグメントセレクタを見るセグメントセレクタは0x08なので1番目のセグメントディスクリプタを見るセグメントディスクリプタのベースアドレスが0x00000500であるので、この値と論理アドレスのオフセット(プログラムにはこのオフセットの値をアドレスとして書きます)0x00001000を足して0x00001500を計算してリニアアドレスに変換してアクセスするとなります。リニアアドレスに変換する作業はCPUが勝手に計算してくれますここで注意していただきたいのですが、プログラム中ではオフセットであるアドレスだけを主に書いています論理アドレスはセグメントレジスタの値とアドレス(オフセット)の組み合わせですので、プログラム中に明示的にセグメントレジスタを指定しなければ、CPUはどのセグメントセレクタを使っていいのかわかりません。使うセレクタはCS(コード)、DS(データ)、SS(スタック)だけですので、プログラムでは特にどのセグメントセレクタを使うのかを書く必要はありません例えばプログラムを実行するのなら決まってCSですし、データの読み書きはDSを使いますPOP、PUSH命令であれば自動的にSSのセレクタを使うので、プログラムにはアドレス(オフセット)だけを書きますES、FS、GSのセグメントセレクタを意図的に使いわける場合は明示的に指定する必要があります(またはES、FS、GSレジスタを使う命令を使うときには意識して使う必要があります)セグメントレジスタのセグメントセレクタプロテクティッドモードはメモリを保護するモードでメモリにアクセスする権限を設定できますアクセス権限にはレベルがあり、特権レベルと呼ばれます。Level)といいますRPLはセグメントセレクタの値で設定されます。プロテクティッドモードへの移行とA20。