[PR]100万円が無料で当たる!:今すぐ応募して現金を当てよう!

プロテクトモードに移行し、各セレクタを32bit化することは できました。しかし、 BIOSが提供する割り込みハンドラはリアルモード用です。 プロテクトモードの割り込みはプロテクトモードで実行されます。 この状態で割り込みを許可するとハングアップします。
割り込みが起きたとき、 CPU は IDTR が指すベースアドレスをベースとした 配列にアクセスします。 割り込みハンドラを用意するには、 IDTRとこの配列を設定すれば良いことになります。 この配列の各エントリには、 リアルモードでは4バイトのfarポインタ、 プロテクトモードでは8バイトのdescriptorを与えます。 起動時に 割り込みハンドラとして 0000h:0000hからの400バイトが使われるのは、 IDTRのベースアドレスには0、 リミットには3FFhが設定されているためです。
割り込み用のdescriptorは次の構造体です。

オフセットサイズ機能
+00h2-byteハンドラのオフセットの下位16bitです。
+02h2-byteハンドラのセレクタです。
+04h1-byte予約(0)
+05h1-bytedescriptorの種類です。 GDTと同じものですが、 bit 4-0には次のいずれかの値を設定します。
0Eh:32-bit 割り込みゲート0Fh:32-bit トラップゲート
+06h2-byteハンドラのオフセットの上位16bitです。

gccやg++で使う場合は、例えば 次のように構造体を定義すると良いでしょう。

割り込みゲートの機能はリアルモードの割り込みと基本的に同じです。
トラップゲートは割り込みゲートと似ていますが、 cliが自動実行されない点が違います。

後はg_interrupt_descは目的に応じて 初期化しておき、 次のようにIDTRを設定します。


32bitモードのハードウェア割り込みハンドラには、 仮想86モードに切り替え、対応する BIOSのハンドラを呼び出すものを書いておきます。 これでIDTの設定については良いのですが、 AT互換機ではもう1つ設定が必要になります。
それは、CPUの例外で使われる割り込み(0x00〜0x1F)と ハードウェア割り込み(0x08〜0x0f,0x70〜0x77)の 割り込み番号がBIOSの設定のままでは衝突しているという点です。
特に、0x0d (#GP) が衝突しているのが致命的です。
このままでは問題を起こしますので、 割り込みコントローラ(PIC)にアクセスして、 ハードウェア割り込みで使う割り込み番号を別の値に 移動させます。
IRQ8〜IRQ15は移動させる必要はありませんが、 仮にそれらをまとめて 0x20〜0x2f に移動させるのであれば、 インラインアセンブラで書いた次のコードが使えます。
なお、ユーザモードや仮想86モードの割り込みは#GP(0)を起こすため、 DPLを0にしておけばINT 21h等との衝突は起こりません。


これで割り込み許可の準備ができましたので、 NMIとハードウェア割り込みを許可します。



2005-09-04: ページ作成 (最終更新)
Copyright (C) 2005 hoverkid, all rights reserved.
[PR]話題の新車を無料プレゼント中:必ず当る抽選会!今すぐ応募で簡単GET