Bonjour,
Je suis en train d'essayer de créer un mini-kernel en C, lancé à partir d'un bootloader en assembleur. Le bootloader fonctionne (il est inspiré d'un tutoriel), j'ai réussi à le tester avec un noyau en assembleur. Son rôle est simplement de charger le code du noyau à l'adresse 0x1000, de passer en mode protégé (je n'initialise pas la ligne A20 pour le moment, mais je ne pense pas que ce soit nécessaire puisque je n'excède pas les 1Mb) puis d'appeler le noyau.
Le problème est au niveau du noyau. Pas de problème de compilation, mais quand je teste le tout (Bochs), les variables globales de mon prgrammes en C semblent foirer.
Je vous mets le code complet :
Code boot.asm : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 %include "gdtnasm.inc" [BITS 16] ; We need 16-bit intructions for Real mode [ORG 0x7C00] ; The BIOS loads the boot sector into memory location 0x7C00 reset_drive: mov [bootdrive], dl ; saving boot drive mov ah, 0 ; RESET-command int 13h ; Call interrupt 13h or ah, ah ; Check for error code jnz reset_drive ; Try again if ah != 0 mov ax, 0 mov es, ax mov bx, 0x1000 ; Destination address = 0000:1000 mov ah, 02h ; READ SECTOR-command mov al, 02h ; Number of sectors to read = 1 mov ch, 0 ; Cylinder = 0 mov cl, 02h ; Sector = 2 mov dh, 0 ; Head = 0 int 13h ; Call interrupt 13h or ah, ah ; Check for error code jnz reset_drive ; Try again if ah != 0 cli ; Disable interrupts, we want to be alone xor ax, ax mov ds, ax ; Set DS-register to 0 - used by lgdt lgdt [gdt_desc] ; Load the GDT descriptor mov eax, cr0 ; Copy the contents of CR0 into EAX or eax, 1 ; Set bit 0 mov cr0, eax ; Copy the contents of EAX into CR0 jmp 08h:clear_pipe ; Jump to code segment, offset clear_pipe [BITS 32] ; We now need 32-bit instructions clear_pipe: mov ax, 10h ; Save data segment identifyer mov ds, ax ; Move a valid data segment into the data segment register mov fs, ax mov gs, ax mov ss, ax ; Move a valid data segment into the stack segment register mov esp, 090000h ; Move the stack pointer to 090000h mov ax, 18h mov es, ax call 08h:01000h ; Jump to section 08h (code), offset 01000h end: jmp end ; Variables bootdrive: db 0 gdt: ; Address for the GDT ; Null Segment gdt_null desc 0,0,0 ; Code Segment gdt_code desc 0, 0xFFFFF, D_CODE + D_READ + D_BIG + D_BIG_LIM ; Data Segment gdt_data desc 0, 0xFFFFF, D_DATA + D_WRITE + D_BIG + D_BIG_LIM ; Video Segment gdt_video desc 0x0B8000, 0xFA0, D_DATA + D_WRITE + D_BIG gdt_end: ; Used to calculate the size of the GDT gdt_desc: ; The GDT descriptor dw gdt_end - gdt - 1 ; Limit (size) dd gdt ; Address of the GDT times 510-($-$$) db 0 ; Fill up the file with zeros dw 0AA55h ; Boot sector identifyer
Code start.c : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 unsigned char* video_mem = (unsigned char *)0xB8000; void clrscr(void); void os_main(void) { clrscr(); *((unsigned char *)0xB8000) = 'A'; *((unsigned char *)0xB8001) = 0x1B; } void clrscr(void) { unsigned char *vidmem = video_mem; const long size = 80 * 25; long loop; // Clear visible video memory for (loop=0; loop < size; loop++) { *vidmem++ = 0; *vidmem++ = 0xF; } }
Le résultat du truc, c'est qu'il m'affiche le caractère 'P', mais il n'efface pas l'écran. Si je remplace la ligne :
par
Code : Sélectionner tout - Visualiser dans une fenêtre à part unsigned char *vidmem = video_mem;
ça marche. Le problème semble donc venir des variables globales... Et j'avoue que j'ai du mal à l'expliquer.
Code : Sélectionner tout - Visualiser dans une fenêtre à part unsigned char *vidmem = (unsigned char *)0xB8000;
Au niveau de la compilation, je fais simplement :
Je travaille sous linux, avec la version par défault de ubuntu.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 gcc -c start.c ld --oformat binary -e os_main -Ttext 0x1000 -o kern.bin start.o
Autre chose, qui est sans doute lié, c'est que je ne peux pas déclarer des fonctions dans un autre fichier que je link. Là de nouveau, pas de problème de compilation, mais la fonction ne fait rien (d'apparent) et ne retourne jamais.
Merci de votre aide
CalvinGhost
Partager