2017-09-17 5 views
0

Je fais un système d'exploitation et je suis coincé au GDT. J'ai essayé différents tutoriels, tels que http://www.osdever.net/bkerndev/Docs/gdt.htm et http://www.jamesmolloy.co.uk/tutorial_html/4.-The%20GDT%20and%20IDT.html, mais mon ordinateur plante toujours. Comment puis-je réparer cela? J'utilise grub pour que le noyau soit déjà en mode protégé.Comment initialiser le GDT?

boot.asm:

section .multiboot 
multiboot_start: 
dd 0xe85250d6 
dd 0 
dd multiboot_end - multiboot_start 
dd 0x100000000 - (0xe85250d6 + 0 + (multiboot_end - multiboot_start)) 
dw 0 
multiboot_end: 
section .text 
global gdt_flush 
extern gp 
gdt_flush: 
lgdt [gp] 
mov ax, 0x10 
mov ds, ax; This line restarts the computer 
mov es, ax 
mov fs, ax 
mov gs, ax 
mov ss, ax 
jmp 0x08:flush2 
flush2: 
ret    
extern kernel_main 
start: 
mov esp, stack_space 
call kernel_main 
hlt 
section .bss 
resb 10240 
stack_space: 

kernel.c:

#include <tty.h> 
#include <log.h> 
struct gdt_entry { 
unsigned short limit_low; 
unsigned short base_low; 
unsigned char base_middle; 
unsigned char access; 
unsigned char granularity; 
unsigned char base_high; 
} __attribute__((packed)); 
struct gdt_ptr { 
unsigned short limit; 
unsigned int base; 
} __attribute__((packed)); 
struct gdt_entry gdt[3]; 
struct gdt_ptr gp; 
extern void gdt_flush(); 
void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran) { 
gdt[num].base_low = (base & 0xFFFF); 
gdt[num].base_middle = (base >> 16) & 0xFF; 
gdt[num].base_high = (base >> 24) & 0xFF; 
gdt[num].limit_low = (limit & 0xFFFF); 
gdt[num].granularity = ((limit >> 16) & 0x0F); 
gdt[num].granularity |= (gran & 0xF0); 
gdt[num].access = access; 
} 
void gdt_install() { 
gp.limit = (sizeof(struct gdt_entry) * 3) - 1; 
gp.base = &gdt; 
gdt_set_gate(0, 0, 0, 0, 0); 
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); 
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); 
gdt_flush(); 
} 
void kernel_main(void){ 
initterm(); 
put("Initializing system...\n"); 
gdt_install(); 
} 

linker.ld:

SECTIONS 
{ 
. = 1M; 
.text BLOCK(4K) : ALIGN(4K) 
{ 
    *(.multiboot) 
    *(.text) 
} 
.data BLOCK(4K) : ALIGN(4K) 
{ 
    *(.data) 
} 
.bss BLOCK(4K) : ALIGN(4K) 
{ 
    *(COMMON) 
    *(.bss) 
} 
} 

Makefile:

LINKFILES=kernel/boot.o kernel/kernel.o kernel/libk/string/strlen.o kernel/libk/tty/tty.o kernel/libk/ioport/inb.o kernel/libk/ioport/outb.o kernel/libk/serial/serwritechar.o kernel/libk/serial/writetoserial.o kernel/libk /tty/print.o kernel/libk/log/put.o 
compile: 
cd kernel && make compile 
build: 
ld -o devos.bin -Tkernel/linker.ld $(LINKFILES) -melf_i386 
mkdir -p iso/boot/grub 
mv devos.bin iso/boot/devos.bin 
cp grub.cfg iso/boot/grub/grub.cfg 
grub-mkrescue -o devos.iso iso 
.SILENT: 
all: compile build 

noyau makefile:

compile: 
cd libk && make compile 
nasm -felf32 boot.asm 
gcc -c kernel.c -I libk -std=gnu99 -m32 -ffreestanding 
+0

Vous devrez poster votre code et nous montrer votre tentative qui échoue que vous vous attendez à travailler. –

+2

Avez-vous essayé de le faire seul dans le débogueur intégré de BOCHS, ou d'une autre façon de déboguer? –

+0

Oui, j'ai utilisé les instructions hlt et le problème est dans la ligne 'mov ds, ax' – MSathieu

Répondre

2

Votre code semble être correct en supposant que initterm que vous ne nous montre pas ne dispose pas d'un bug ou tourne sur les interruptions avec les instructions STI. Des interruptions non gérées ou pas de table de descripteurs d'interruption (IDT) appropriée provoquent une triple erreur.

Je suppose que le problème peut ne pas être du tout. En règle générale, si vous créez des objets ELF qui ont l'intention d'être chargés par un chargeur de démarrage compatible Multiboot (2), vous devez définir explicitement le point d'entrée dans votre script d'éditeur de liens. Le définir indique à l'éditeur de liens où vous voulez que le bootloader commence à exécuter votre code. Dans votre cas, vous avez une étiquette start dans votre code, donc je pense que vous vouliez que ce soit le point d'entrée.

En haut de votre script linker ajouter:

ENTRY(start) 

L'éditeur de liens attend à ce que le symbole start sera un label mondial. Dans votre fichier assembleur avec l'en-tête multiboot2 assurez-vous start est mondiale avec cette ligne:

global start 

Cela devrait être suffisant pour régler correctement le point d'entrée. Si vous placez explicitement une directive ENTRY dans votre script d'éditeur de liens, l'éditeur de liens vous avertira s'il ne trouve pas l'étiquette globale que vous définissez comme point d'entrée et vous indiquera l'adresse du point d'entrée par défaut. La valeur par défaut est généralement l'adresse de mémoire virtuelle de départ (VMA) dans l'objet ELF. Dans votre cas, ce serait 0x100000.

Vous n'obtiendrez aucun avertissement si la directive ENTRY n'est pas présente. Dans ce cas, l'éditeur de liens recherche généralement un libellé global appelé start et s'il ne le trouve pas, il définit le point d'entrée au VMA de départ de l'objet ELF. La spécification d'une adresse de départ avec la directive ENTRY dans le script de l'éditeur de liens vous indiquera s'il y a un problème et quel VMA il a utilisé comme point d'entrée s'il est manquant.

Règle générale: Toujours spécifier un point d'entrée dans le script de l'éditeur de liens avec la directive ENTRY et exporter globalement cette étiquette dans votre code.