30日でできる!OS自作入門6日目

 6日目は割り込み処理について学ぶ。

picの初期化

 5日目でGDTとIDTを初期化をしたが、割り込み処理のためにはPICの設定も必要である。PICは一つの割り込み信号しか受け付けられないCPUを補助するもので、8つの割り込み信号をまとめて1つの信号をCPUに送るものである。マザーボードにはマスターPICとスレイブPICがあり、スレイブPICから割り込み信号を送られてもマスターPICが反応しなければCPUに割り込みを通知されない仕組みになっている。下の図のIRQは割り込み信号のことである。
f:id:achax0511:20181220141513j:plain
川合秀実(2006)・『30日でできる!OS自作入門』 p.127 ,株式会社マイナビ

割り込み番号の振り分け

 以下のPICの初期化プログラムでは、制御データICW2で割り込み信号に対して割り込み番号を振り分けている。そのためこの例ではIRQ0、IRQ1から割り込み信号が送られるとそれぞれ割り込み番号20、21に対応する処理をする。

void init_pic(void)
/* PICの初期化 */
{   //それ以外の処理は省略
 io_out8(PIC0_ICW2, 0x20  ); /* IRQ0-7は、INT 20-27で受ける */
 io_out8(PIC1_ICW2, 0x28  ); /* IRQ8-15は、INT 28-2fで受ける */                             
}

割り込みハンドラ

 キーボードの割り込み信号はIRQ1、マウスのキーボードはIRQ12なので割り込み番号0x21,0x2cに対応する処理(割り込みハンドラ)を作成する。今回はキーボード入力やマウス操作すると文字が表示される割り込みハンドラを作成する。割り込みは実行している処理を中断して行うので、割り込み前のデータを保存して後に処理を再開できるようにする必要がある。そのためアセンブラ言語でプログラムを書く必要がある。
 以下のプログラムが割り込みハンドラになる。大まかに述べるとこのプログラムでは処理前のレジスタの値をスタックに入れ、C言語で書いた文字を表示する関数を呼び出し、スタックをとりだして割り込み前のレジスタの値に戻している。

_asm_inthandler21:
 PUSH ES
 PUSH DS
 PUSHAD
 MOV EAX,ESP
 PUSH EAX
 MOV AX,SS
 MOV DS,AX
 MOV ES,AX
 CALL _inthandler21
 POP EAX
 POPAD
 POP DS
 POP ES
 IRETD

次にIDTに_asm_inthandler21を設定する。その結果キーボードを入力すると割り込み処理が行われて文字が表示されるようになった。しかし、その後マウスも同じ要領で割り込みハンドラーを作成するが割り込み処理がうまく行われなかった。

f:id:achax0511:20181220180549j:plain
キーボードの割り込み処理