Also hier der Code für meine GDT:
struct gdt_entry
{
uint8_t limit_0_7;
uint8_t limit_8_15;
uint8_t base_0_7;
uint8_t base_8_15;
uint8_t base_16_23;
uint8_t access;
uint8_t flags_limit;
uint8_t base_24_31;
}__attribute__((packed));
typedef struct gdt_entry gdt_entry;
gdt_entry gdt[GDT_ENTRIES];
struct gdt_ptr
{
uint16_t gdt_limit;
void *gdt_ptr;
}__attribute__((packed)) gdt_p = {.gdt_limit = GDT_ENTRIES*8-1, .gdt_ptr = gdt};
void gdt_set_entry(uint32_t limit, uint32_t base, uint8_t accessbyte, uint8_t flags, unsigned int index)
{
gdt_entry *g = &(gdt[index]);
g->limit_0_7 = (uint8_t) limit;
g->limit_8_15 = (uint8_t) (limit >> 8);
g->base_0_7 = (uint8_t) base;
g->base_8_15 = (uint8_t) (base >> 8);
g->base_16_23 = (uint8_t) (base >> 16);
g->access = accessbyte;
g->flags_limit = (((uint8_t) (limit >> 16)) & 0b00001111) | (flags << 4);
g->base_24_31 = (uint8_t) (base >> 24);
}
void setup_gdt()
{
gdt_set_entry(0, 0, 0, 0, 0);
gdt_set_entry(0xFFFFFFFF, 0x00000000, 0x9A, 0xD, 1); //Kernel-Code
gdt_set_entry(0xFFFFFFFF, 0x00000000, 0x92, 0xD, 2); //Kernel-Data
gdt_set_entry(0xFFFFFFFF, 0x00000000, 0xFA, 0xD, 3); //User-Code
gdt_set_entry(0xFFFFFFFF, 0x00000000, 0xF2, 0xD, 4); //User-Data
gdt_set_entry(((uint32_t) tss_ptr) + sizeof(tss_entry), (uint32_t) tss_ptr, 0xE9, 0, 5);
asm volatile("lgdt %0" : : "m" (gdt_p));
asm volatile("ltr %%ax" : : "a" (5 << 3));
gdt_reload();
tss_ptr->ss0 = gdt_get_selector(2, 0, 0b00);
tss_ptr->esp0 = (uint32_t) kernel_stack;
}
Hier ist GDT_ENTRIES auf 7 festgelegt. tss_ptr ist ein Zeiger auf ein Objekt der folgenden Struktur:
struct tss_entry_struct
{
uint32_t prev_tss;
uint32_t esp0;
uint32_t ss0;
uint32_t esp1;
uint32_t ss1;
uint32_t esp2;
uint32_t ss2;
uint32_t cr3;
uint32_t eip;
uint32_t eflags;
uint32_t eax;
uint32_t ecx;
uint32_t edx;
uint32_t ebx;
uint32_t esp;
uint32_t ebp;
uint32_t esi;
uint32_t edi;
uint32_t es;
uint32_t cs;
uint32_t ss;
uint32_t ds;
uint32_t fs;
uint32_t gs;
uint32_t ldt;
uint16_t trap;
uint16_t iomap_base;
} __packed;
Und schließlich die IDT:
idt:
times IDT_ENTRIES*8 db 0
idtr:
dw (IDT_ENTRIES*8)-1
dd idt
setup_idt:
lidt [idtr]
%macro idt_entry 1
mov edx, interrupt_stub_%1
mov [idt+8*(%1)], dx
call get_code_segment
mov word [idt+8*(%1)+2], ax
mov word [idt+8*(%1)+4], 0x8E00
shr edx, 16
mov [idt+8*(%1)+6], dx
%endmacro
%macro idt_entry_ec 1
mov edx, interrupt_stub_ec_%1
mov [idt+8*(%1)], dx
call get_code_segment
mov word [idt+8*(%1)+2], ax
mov word [idt+8*(%1)+4], 0x8E00
shr edx, 16
mov [idt+8*(%1)+6], dx
%endmacro
%macro idt_entry_user 1
mov edx, interrupt_stub_%1
mov [idt+8*(%1)], dx
call get_code_segment
mov word [idt+8*(%1)+2], ax
mov word [idt+8*(%1)+4], 0xEE00
shr edx, 16
mov [idt+8*(%1)+6], dx
%endmacro
idt_entry 0
idt_entry 1
...
In den entsprechenden Handlern wird dann der Standart-Handler aufgerufen. Der entspricht wieder dem im Tutorial.