基本的に言えば、作業が完了した後にデフォルト ハンドラーを呼び出さない限り、完了したことを PIC (プログラマブル割り込みコントローラー) に通知する必要があります。デフォルト ハンドラーがこれを行い、EOI を送信します (終了の割り込み信号) を PIC(s) に送信します。PIC は、現在の割り込みが完了したことを通知するまで、割り込みを再度発生させません。
32 ビット プロテクト モードでこれを行うコードは、次のようになります。適切に登録されたユーザー コールバック関数に渡すだけで、すべての IRQ に汎用ハンドラーを使用していることに注意してください。両方入れました。
まず、汎用 IRQ ハンドラ
irq_handler:
push ebp
mov ebp, esp
add ebp, 8
mov eax, [ebp +registers_t.int_no]
cmp eax, IRQ7 ; this just dumps spurious IRQ7 interrupts
je .irqHandlerDone
cmp eax, IRQ8 ; if it's IRQ0 - IRQ7, the first controller fired the int, otherwise the slave controller did
jb .slaveResetDone
.resetSlave:
mov al,20H ; send End-Of-Interrupt signal
out 0xA0,al ; to the 8259 _slave_ Programmable Interrupt Controller
.slaveResetDone:
.resetMaster:
mov al, 0x20 ; send End-Of-Interrupt signal
out 0x20, al ; to the 8259 master Programmable Interrupt Controller
mov eax, [ebp + registers_t.int_no]
shl eax, 2 ; x4
mov esi, interrupt_handlers
add esi, eax ; esi --> interrupt_handlers[int_no]
cmp dword [esi], 0
je .irqHandlerDone
call [esi]
.irqHandlerDone:
pop ebp
ret
次に、IRQ1 (キーボード) ハンドラーです。登録関数は、関数のオフセットをinterrupt_handlers
32 ビット アドレスのテーブル ( ) にコピーするだけです。私はフラット メモリ モードです (4GB アドレス可能、ES は既に書き込み可能なデータ セグメントのセグメント セレクターを保持しています。0xB8000 + 79*2 は単に 80x25 モード 3 テキスト画面の右上の文字を指します)。
; keyboard IRQ handler
irq1Handler:
push ebp
mov ebp, esp
add ebp, 8+4
in al, 0x60
mov bl, al
mov byte [port60], al
in al, 0x61
mov ah, al
or al, 0x80
out 0x61, al
xchg ah, al
out 0x61, al
and bl, 0x80
jnz .done
pusha
;mov al, [port60]
;call outputChar
mov edi, 0xB8000 + 79*2
mov al, [port60]
mov [es:edi], al
popa
.done:
pop ebp
ret
port60 db 0
このコードは、James M のチュートリアルから引用しています。http ://www.jamesmolloy.co.uk/tutorial_html/5.-IRQs%20and%20the%20PIT.html
OSDev.org ( http://wiki.osdev.org/Main_Page ) で、ハードウェアへのインターフェースについて読むことができる多くの情報があります。
更新:
これは DosBox で機能する 16 ビット ISR です。
;-----------------------------------------------------
; handles int 0x09
;-----------------------------------------------------
keyhandler:
cli
pusha
in al, 0x60 ; get key data
mov bl, al ; save it
mov byte [port60], al
in al, 0x61 ; keybrd control
mov ah, al
or al, 0x80 ; disable bit 7
out 0x61, al ; send it back
xchg ah, al ; get original
out 0x61, al ; send that back
mov al, 0x20 ; End of Interrupt
out 0x20, al ;
and bl, 0x80 ; key released
jnz done ; don't repeat
mov al, [port60]
;
; do something with the scan-code here
;
done:
popa
iret
port60 db 0 ; where we'll store the scan-code