Ontwerp en bouw een besturingssysteem/Blue Screen of Death/Interrupt Descriptor Table
Het opzetten van een Interrupt Descriptor Table lijkt heel erg op hoe dat ging met de GDT. Behalve een soort pointer naar de nieuwe tabel, definiëren we in idt.h
ook weer een structuur voor de descriptors. Opnieuw maken we gebruik van twee globale variabelen.
Structuur
[bewerken]/kernel/include/idt.h
#ifndef __IDT_H
#define __IDT_H
typedef struct Idt_Pointer Idt_Pointer;
typedef struct Idt_Descriptor Idt_Descriptor;
// Deze functie is in idt.asm gedefinieerd.
extern void Idt_Load();
// Speciale pointer met de locatie en de lengte van de IDT.
struct Idt_Pointer
{
// De index van de laatste byte die onderdeel is van de IDT.
uint16 limit;
// De index van de eerste byte die onderdeel is van de IDT.
uint32 base;
} __attribute__((packed));
// Een descriptor voor in de IDT.
struct Idt_Descriptor
{
// Bits 0-15 van de offset.
uint16 offsetLow;
// De segment selector.
uint16 segmentSelector;
// Altijd 0.
byte reserved;
// De belangrijkste attributen.
byte attributes;
// Bits 16-31 van de offset.
uint16 offsetHigh;
} __attribute__((packed));
// Voor de code in idt.asm:
// IDT met ruimte voor het maximaal aantal mogelijke descriptors.
Idt_Descriptor idt[256];
// Pointer naar de IDT.
Idt_Pointer idtptr;
#endif // __IDT_H
Laden van de IDT
[bewerken]Ook voor het laden van de tabel als IDT is een assembler functie nodig, maar deze is iets simpeler:
/kernel/idt.asm
; Functie Idt_Load: laadt de IDT.
global Idt_Load
extern idtptr
Idt_Load:
; De IDT laden.
lidt [idtptr]
ret
In de C code maken we ook nog een functie die de IDT initialiseerd en laadt:
/kernel/idt.c
void Idt_Initialize()
{
// TODO: Vervang 256 door een constante.
// Vul de gehele IDT met nullen:
Memory_Set(&idt, 0, sizeof(Idt_Descriptor) * 256);
// Maak de IDT pointer:
idtptr.base = &idt;
idtptr.limit = (sizeof(Idt_Descriptor) * 256) - 1;
// Alle Interrupt Service Routines hier toevoegen d.m.v. Idt_SetDescriptor():
// ...
// Laadt de IDT.
Idt_Load();
}
Descriptors laden
[bewerken]Ten slotte is er nog de hierboven genoemde functie nodig om een descriptor in de IDT te laden. Het prototype voor de functie is hieronder gegeven, de implementatie zou je zelf moeten kunnen schrijven. Kijk hiervoor goed naar de theorie en de Idt_Descriptor
structuur hierboven.
/kernel/idt.c
// Stelt een descriptor op <index> in de IDT in.
void Idt_SetDescriptor(byte index, unint offset, uint16 selector, byte attributes)
{
...
}