32bit割り込みハンドラの設定では、
割り込みハンドラのインストール方法を説明しました。
では、割り込みハンドラはどのように実装すれば良いのでしょうか?
これを実装するには、まず割り込み発生時にCPUが行う処理を
知る必要があります。
今回はDPLを0に設定した
32bitの割り込みゲートに限定して説明します。
割り込みが起きたときのCPUのモードにより、
呼び出されたときのスタックの内容は変わります。
CPUのモードは次の3種類です。
| スタックアドレス | 対象 | 内容 |
| (+00h) | (kernel,user,v86) | (一部例外の場合のみ)エラーコード |
| +00h | kernel,user,v86 | 呼び出し元のEIPです。 |
| +04h | kernel,user,v86 | 呼び出し元のCSです。 |
| +08h | kernel,user,v86 | 呼び出し元のEFLAGSです。 |
| +0Ch | user,v86 | 呼び出し元のESPです。 |
| +10h | user,v86 | 呼び出し元のSSです。 |
| +14h | v86 | 呼び出し元のESです。 |
| +18h | v86 | 呼び出し元のDSです。 |
| +1Ch | v86 | 呼び出し元のFSです。 |
| +20h | v86 | 呼び出し元のGSです。 |
; extern "C" void timer_handler(void); timer_entry: cld push ds push es pushad mov ax, 10h mov ds, ax mov es, ax call _timer_handler popad pop es pop ds iret
gpfault_entry: cld push ds push es pushad mov ax, 10h mov ds, ax mov es, ax push esp call _gpfault_handler add esp, 4 popad pop es pop ds add esp, 4 iret
struct GPFAULT_DATA
{
unsigned edi;
unsigned esi;
unsigned ebp;
unsigned dummy_esp;
unsigned ebx;
unsigned edx;
unsigned ecx;
unsigned eax;
unsigned saved_es;
unsigned saved_ds;
unsigned error_code;
unsigned eip;
unsigned cs;
unsigned eflags;
unsigned user_esp;
unsigned user_ss;
unsigned v86_es;
unsigned v86_ds;
unsigned v86_fs;
unsigned v86_gs;
};
extern "C" void gpfault_handler(GPFAULT_DATA *pdata)
{
if (pdata->eflags & 0x20000) {
// 仮想86用モードから呼ばれたときの処理
} else if ((pdata->cs & 0x3) != 0) {
// ユーザモードから呼ばれたときの処理
} else {
// カーネルから呼ばれたときの処理
}
}
次の例は、割り込みハンドラではなく
仮想86モードへの切り替えを行うコードです。switch_to_v86: push dword [V86_GS] push dword [V86_FS] push dword [V86_DS] push dword [V86_ES] push dword [V86_SS] push dword [V86_ESP] mov eax, [V86_EFLAGS] or eax, 20000h ; VM bit push eax push dword [V86_CS] push dword [V86_EIP] iret