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 :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
unsigned char *vidmem = video_mem;
par
Code : Sélectionner tout - Visualiser dans une fenêtre à part
unsigned char *vidmem = (unsigned char *)0xB8000;
ça marche. Le problème semble donc venir des variables globales... Et j'avoue que j'ai du mal à l'expliquer.

Au niveau de la compilation, je fais simplement :
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
Je travaille sous linux, avec la version par défault de ubuntu.

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