Précédent   Forum des professionnels en informatique > Autres langages > Assembleur > x86 32-bits / 64-bits
x86 32-bits / 64-bits Architectures x86 32/64 bits et leurs outils (assembleurs, debuggers, émulateurs...)
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 01/02/2012, 11h40   #1
Candidat au titre de Membre du Club
 
Inscription : mars 2006
Messages : 100
Détails du profil
Informations forums :
Inscription : mars 2006
Messages : 100
Points : 12
Points : 12
Par défaut Bootloader et Kernel, passage mode protégé ↔ réel

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é :
Code :
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
Et voici le code du kernel :
Code :
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
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.

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 :
Code :
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
et kernel2
Code :
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
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.


Merci de votre aide.
qnop est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 22h44   #2
Membre expérimenté
 
Avatar de edfed
 
être humain
Inscription : décembre 2007
Messages : 465
Détails du profil
Informations professionnelles :
Activité : être humain

Informations forums :
Inscription : décembre 2007
Messages : 465
Points : 582
Points : 582
comment veux tu faire du mode protegé si tu continue à utilser l'int 10h du bios?

un coup d'oeil sur la doc
Citation:

INT 10,9 - Write Character and Attribute at Cursor Position


AH = 09
AL = ASCII character to write
BH = display page (or mode 13h, background pixel value)
BL = character attribute (text) foreground color (graphics)
CX = count of characters to write (CX >= 1)


returns nothing


- does not move the cursor
- in graphics mode (except mode 13h), if BL bit 7=1 then
value of BL is XOR'ed with the background color
montre que le caractère B ne s'affiche pas car tu ne dis pas correctement à INT 10h ce qu'elle doit faire. tout simplement.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
;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

utilise ce type de doc quand tu codes avec les interruptions bios et la memoire du mode protegé, ça aide enormement:
http://docs.huihoo.com/help-pc/int-int_10.html



mais pour afficher des pixels (ou des caractères selon le mode), il n'y à pas besoin du bios, et donc, pas besoin de repasser en mode reel.
en utilisant un descripteur de segment pour la zone de mémoire à utiliser.
d'ailleur, en mode reel aussi on à pas besoin du bios pour afficher, car c'est très lent.
__________________
http://www.pending.me.uk/nmc/bla_1356091200.png
Vivement 21/12/2012
edfed est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 17h23.


 
 
 
 
Partenaires

Hébergement Web