Ontwerp en bouw een besturingssysteem/Blue Screen of Death/Global Descriptor Table
Uiterlijk
Zoals in de theorie aangegeven, moeten we een tabel met drie descriptors maken. Daarna hebben we een soort pointer nodig met de offset van de eerste en laatste byte van de nieuwe tabel, en daarmee de tabel als GDT instellen. De code in gdt.h
definieert een structuur voor de pointer en voor de descriptors, en maakt gebruik van twee globale variabelen.
/kernel/include/gdt.h
#ifndef __GDT_H
#define __GDT_H
typedef struct GdtPtr GdtPtr;
typedef struct GdtEntry GdtEntry;
// Speciale pointer met de locatie en de lengte van de GDT.
struct GdtPtr
{
// De index van de laatste byte die onderdeel is van de GDT.
uint16 limit;
// De index van de eerste byte die onderdeel is van de GDT.
uint32 base;
} __attribute__((packed));
// Een descriptor voor in de GDT.
struct GdtEntry
{
// Bits 0-15 van de limiet.
uint16 limitLow;
// Bits 0-15 van de basis.
uint16 baseLow;
// Bits 16-23 van de basis.
byte baseMiddle;
// De belangrijkste attributen.
byte attributes;
// Bits 16-20 van de limiet, en overige attributen.
byte extension;
// Bits 24-31 van de basis.
byte baseHigh;
} __attribute__((packed));
// Voor de code in gdt.asm:
// GDT met ruimte voor drie descriptors.
GdtEntry gdt[3];
// Pointer naar de GDT.
GdtPtr gdtptr;
#endif // __GDT_H
Daarnaast heb je een functie nodig om de tabel als GDT te laden, en dat kan alleen vanuit assembler:
/kernel/include/gdt.asm
; Functie LoadGdt: laadt de GDT, en laadt CS en de andere segment selectors.
global LoadGdt
extern gdtptr
LoadGdt:
; De GDT laden.
lgdt [gdtptr]
; De data segment selectors instellen.
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; D.m.v. een far jump de code segment selector CS instellen.
jmp 0x08:landingpad
landingpad:
ret
Maak nu nog een functie om een GDT descriptor te laden in de tabel, en roep die functie en de LoadGdt functie aan bij het laden.