Bonjour à vous tous !
Me revoilà, et encore avec des problèmes (pour changer). Je me suis mis il y a plus ou moins 1 mois a l'assembleur et, comme tous débutant, on veut faire de grandes choses, comme coder un OS comme Windows (version -14 pour ma part :p). Je suis le tutoriel sur le cours de Pépin, très bien fait en plus, mais voilà, je suis arrivé au mode protégé. Donc, plus d'interruption et, pour le mode VESA, ça devient compliqué haha :p.
Pour le mode vesa, en recherchant, je suis tombé sur ce lien où une des personnes explique (en gros) comment utiliser le mode VESA 2.0 en mode protégé. Mais voilà, vu que je suis déjà en mode protégé, quelques soucis « subsistent » (pas sûr de l'écriture) et, donc, je me suis résolu à faire quelques tests en mode texte, plutôt que de faire le kikoolol. J'ai réussi à afficher un écran blanc sans en comprendre le fonctionnement. J'ai donc testé un total de 2 codes. Les deux sont assez légers ^^.
Voila le bootloader, il passe en mode protégé :
Et voici le code du kernel :
Code : 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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135 %define BASE 0x100 ; 0x0100:0x0 = 0x1000 %define KSIZE 50 ; nombre de secteurs a charger [BITS 16] [ORG 0x0] jmp start start: ;initialisation des segments en 0x07C0 mov ax, 0x07C0 mov ds, ax mov es, ax ;Initialisation de la pile(F000h - 8000h) = 7000h mov ax, 0x8000 mov ss, ax mov sp, 0xF000 ;On récupère l'unité de boot utilisée ;Disque dur? Disquette? mov [bootdrv], dl ;charger le noyau xor ax, ax int 0x13 ;On sauvegarde es push es ;On récupère l'adresse du début du kernel mov ax, BASE mov es, ax mov bx, 0 ;On récupère la fonction et le nombre de secteurs à charger mov ah, 2 mov al, KSIZE ;On indique les cylindres et à partir de quel secteur on charge mov ch, 0 mov cl, 2 ;On indique à partir de quelle tête et quelle unité de disque mov dh, 0 mov dl, [bootdrv] int 0x13 ;On restaure es pop es ;initialisation du pointeur sur la GDT ;Calcul de la limite de la GDT (fin - début) mov ax, gdtend mov bx, gdt sub ax, bx ;On met la limite dans le premier champ de la gdt mov word [gdtptr], ax ;Calcul de l'adresse linéaire de la GDT ;Mise à 0 des registres ; xor eax, eax ; xor ebx, ebx ; On récupère l'adresse de base 0x07C0 ; mov ax, ds ; On "déplace d'une lettre vers gauche" l'adresse de base ; 0x07C0 -->> 0x7C00 ; mov ecx, eax ; shl ecx, 4 ; On Ajoute le pointeur de la gdt ; mov bx, gdt ; add ecx, ebx ; On écrit le pointeur dans le champ pointeur de la GDT ; mov dword [gdtptr + 2], ecx mov eax, 0x7C00 add eax, gdt mov dword [gdtptr + 2], eax ;passage en modep cli ;Annule les interruptions lgdt [gdtptr] ;charge la gdt mov eax, cr0 or ax, 1 mov cr0, eax ;On met le bit de poids faible de CR0 a 1 ;On vide le cache interne jmp next next: ;Et on réinitialise les segments ;Les segments de données mov ax, 0x10 mov ds, ax mov fs, ax mov gs, ax mov es, ax mov ss, ax mov esp, 0x9F000 ;Réinitialise le segment de code et "jump" vers le kernel jmp dword 0x8:0x1000 ;Les Variables ;-------------------------------------------------------------------- bootdrv: db 0 ;-------------------------------------------------------------------- gdt:;Pointeur sur le début du segment de la GDT db 0, 0, 0, 0, 0, 0, 0, 0 ;Déscripteur "NULL" gdt_cs: db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0 ;Descripteur de code ;La base est 0x0, la limite 0xFFFFF * 4096 ~= 4go gdt_ds: db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0 ;Descripteur de segment ;Idem gdtend:;Pointeur sur la fin du segment de la GDT ;-------------------------------------------------------------------- gdtptr: dw 0 ; limite dd 0 ; base ;-------------------------------------------------------------------- ;Bourrage de 0 pour arriver a 510 octets times 510-($-$$) db 0 ;On ajoute le mot 0x55AA a l'envers car intel = Little Endian dw 0xAA55
Ce code, comme vous vous en doutez, ne fonctionne évidemment pas, il ne me fait pas "rebooter" le PC comme des fois quand j'essaye d'écrire en dehors d'une zone allouée, mais il laisse l'écran noir, avec le petit curseur qui clignote en haut a gauche, pas très utile donc.
Code : 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 [bits 32] org 0x1000 jmp _start _start: ;On réactive les interruptions et on repasse en mode réel sti mov eax, cr0 dec eax mov cr0, eax ;On réinitialise les différents segments mov ax, 0x100 mov es, ax mov ds, ax ;Et on écrit le magnifique caractère 'B' mov ax, 0x03 int 0x10 xor bx, bx mov cx, 1 xor dx, dx mov ax, 0x02 int 0x10 mov ax, 0x0A42 int 0x10 end: jmp end
Je me suis dit que c'était dut au mode "32 bits", mais ma connaissance là-dedans peut s'apparenter à un petit trou noir.
J'en ai donc profité pour faire un petit bidouillage maison, qui fut tout de même plus convaincant.
Voici mon fichier kernel1 :
et kernel2
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 [bits 32] %define b2 0x0A00 org 0x1000 jmp _start _start: ;On passe en mode réel sti mov eax, cr0 dec eax mov cr0, eax jmp b2:0
Ce code fut plus convaincant, en effet. Il ne m'affiche pas le B, il ne faut pas rêver, mais m'affiche un "fond" cyan de la taille d'un caractère a la place du B.
Code : 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 [bits 16] [org 0x0] jmp _start _start: mov ax, 0xA00 mov es, ax mov ds, ax ;On initialise les segments et on affiche le caractère mov ax, 0x03 int 0x10 xor bx, bx mov cx, 1 xor dx, dx mov ax, 0x02 int 0x10 mov ax, 0x0A42 int 0x10 end: jmp end
Merci de votre aide.
Partager