In one of my previous bootloaders I have written some code to install an IDT, and allow easy interrupt handling management. It is written using NASM, and can be very useful when debugging the bootloader.
I decided to post it here in hopes that it will help anyone out with their code.
Here it is...
Code: Select all
%ifndef __IDT_INC_67343546FDCC56AAB872_INCLUDED__
%define __IDT_INC_67343546FDCC56AAB872_INCLUDED__
bits 32
struc idt_entry
.m_baseLow resw 1
.m_selector resw 1
.m_reserved resb 1
.m_flags resb 1
.m_baseHi resw 1
endstruc
struc idt_ptr
.m_size resw 1
.m_base resd 1
endstruc
_IDT:
%rep 256
istruc idt_entry
at idt_entry.m_baseLow, dw 0
at idt_entry.m_selector, dw 0x8
at idt_entry.m_reserved, db 0
at idt_entry.m_flags, db 010001111b
at idt_entry.m_baseHi, dw 0
iend
%endrep
_IDT_End:
_IDT_Size db _IDT_End - _IDT
_Desc_Size db 8
_IDT_Ptr:
istruc idt_ptr
at idt_ptr.m_size, dw 0
at idt_ptr.m_base, dd 0
iend
;*********************
; Loads idt into idtr
;*********************
IDT_Load:
cli
lidt [_IDT_Ptr]
ret
;********************
; Installs idt
;********************
IDT_Install:
pusha
cli
mov word [_IDT_Ptr+idt_ptr.m_size], _IDT_Size - 1
mov dword [_IDT_Ptr+idt_ptr.m_base], _IDT
call IDT_Load
popa
ret
;***********************
; Install interrupt gate
; EAX=>Interrupt Number
; EBX=>Base address of ir
;***********************
IDT_SetGate:
pusha
mov edx, 8
mul dx
add eax, _IDT
mov word [eax+idt_entry.m_baseLow], bx
shr ebx, 16
mov word [eax+idt_entry.m_baseHi], bx
popa
ret
%endif
To use it, simply install your IRQs:
Code: Select all
; install idt
call IDT_Install
; install our IRQs
mov eax, 0
mov ebx, IRQ_0
call IDT_SetGate ; installs interrupt 0 handler
mov eax, 1
mov ebx, IRQ_1
call IDT_SetGate ; installs interrupt 1 handler
mov eax, 2
mov ebx, IRQ_2
call IDT_SetGate ; installs interrupt 2 handler
; etc up to 255th handler. This can be looped though

In the series, We will be using C for setting up the IDT and interrupts, so this code might not be used. Who knows...Mabey we might put this in our bootloader...