Précédent   Forum du club des développeurs et IT Pro > Autres langages > Assembleur > Contribuez
Contribuez Contribuez à la FAQ Assembleur ou partagez vos sources
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 13/03/2011, 22h24   #1
edfed
Membre chevronné
 
Avatar de edfed
 
être humain
Inscription : décembre 2007
Messages : 471
Détails du profil
Informations professionnelles :
Activité : être humain

Informations forums :
Inscription : décembre 2007
Messages : 471
Points : 619
Points : 619
Par défaut boot + mode protégé

bon, voici un exemple simple pour démarrer le PC en mode protégé.
évidement, ce code ci n'est pas optimisé pour la taille, le record à ma connaissance étant de même pas 40 octets.
non, ici, il s'agit du code minimal compréhensible par le plus de codeurs possible.
avec les commentaires (en french please) et tout ce qu'il faut pour montrer comment que ça marche ce truc là.

regardez bien, le petit oiseau va sortir

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
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;demarrage et mode protégé      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        org 7c00h               ; l'emplacement où sera chargé et exécuté ce programme
boot:                           ; amorçage = 7c00h (org)
        cli                     ; désactiver les interruptions
        lgdt fword[cs:gdt.r]     ; charger la gdt depuis [cs:gdt.taille], pseudo descripteur de 6 octets
        mov eax,cr0             ; équivalent à "or cr0,1"
        or al,1                  ;   commuter le CPU en mode protégé
        mov cr0,eax             ;   mode protégé activé
        jmp gdt.code:activé     ; équivalent à "mov cs,gdt.code" + "mov eip,activé"
activé:                         ;   la première instruction à exécuter après l'activation du mode protégé
        use32                   ; le code ci dessous est encodé pour le mode 32 bits
        mov ax,gdt.données      ; le registre "ax" pointe vers le contenu de gdt.data
        mov ds,ax               ; le sélecteur "ds" charge le descripteur de segment gdt.data
        mov ah,74h              ; couleur du texte
        mov esi,bonjour         ; pointer vers le message à afficher
        mov ecx,0b8000h         ; pointer vers la mémoire vidéo mode texte
        mov edi,0               ; pointer sur la première cellule de la mémoire vidéo, en haut à gauche
@@:                             ;boucle d'affichage du texte
        mov al,[cs:esi]         ;  charger un caractère dans al
        or al,al                ;  caractère null, al=0?
        je @f                   ;  si oui, sortie
        mov [ecx+edi*2],ax      ; afficher le caractère en rouge sur fond gris, en haut à gauche
        inc esi                 ;  incrémenter les pointeurs
        inc edi                 ;  ...
        jmp @b                  ;goto boucle d'affichage du texte
@@:                             ;  sortie
        hlt                     ; mettre le CPU en pause, comme cela, il consomme peu d'énergie
        jmp $                   ; reboucler infiniment
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
bonjour:                        ; message à afficher
        db 'bonjour',0          ;  bonjour
        align 8                 ; aligner la prochaine instruction sur une adresse multiple de 8 octets.
gdt:    dw 0                    ; aligner la partie 32 bits du pseudo descripteur sur une adresse
.r      dw @f-gdt-1             ; partie 16 bits du pseudo descripteur, taille de la gdt en octets
.linear dd gdt                  ; partie 32 bits du pseudo descripteur, adresse de base linéaire
.code=$-gdt                     ; première entrée dans la gdt (8*1)
dw 0ffffh,0                     ;   4 giga octets, base à l'adresse linéaire 0
db 0,10011010b,11001111b,0      ;   granularité = 4 kilo octets, segment de code, privilège 0, exécutable
.données=$-gdt                  ; second entry in gdt (8*2)
dw 0ffffh,0                     ;   4Gbytes, start at linear 0
db 0,10010010b,11001111b,0      ;   granularity = 4Kbytes, data segment, ring 0, read/write, present,etc...
@@:                             ; used for gdt.size calculation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
libre =  510-(remplissage-$$)   ; define "free" bytes count
remplissage rb libre            ; reserve "free" bytes to make line below at offset 510
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        dw 0aa55h               ; magic number boot mark, used by bios to test if valid boot sector
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d1='0'+libre shr 8 and 0fh       ;
d2='0'+libre shr 4 and 0fh       ;
d3='0'+libre and 0fh             ;
if d1>'9'                       ;
        d1=d1+7                 ;
end if                          ;
                                ;
if d2>'9'                       ;
        d2=d2+7                 ;
end if                          ;
                                ;
if d3>'9'                       ;
        d3=d3+7                 ;
end if                          ;
                                ;
display d1,d2,d3,'h '           ;
display 'libre bytes',13,10      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d1='0'+(510-libre)shr 8 and 0fh  ;
d2='0'+(510-libre)shr 4 and 0fh  ;
d3='0'+(510-libre)and 0fh        ;
if d1>'9'                       ;
        d1=d1+7                 ;
end if                          ;
                                ;
if d2>'9'                       ;
        d2=d2+7                 ;
end if                          ;
                                ;
if d3>'9'                       ;
        d3=d3+7                 ;
end if                          ;
                                ;
display d1,d2,d3,'h '           ;
display 'used bytes',13,10      ;
 
;segment_descriptor:
;.limitl =0
;.basel  =2
;.basem  =4
;.field1 =5
;.type   =0fh
;.s      =10h
;.dpl    =60h
;.p      =80h
;.field2 =6
;.limith =0fh
;.avl    =10h
;.db     =40h
;.g      =80h
;.baseh  =7
donc, comme déjà indiqué dans les commentaires, ce code, il se contente de vraiment très peu de choses.
il désactive les interruptions, comme ça, pas de problème, pas besoin de définir la mystérieuse table de descripteurs d'interruptions (IDT).

suite à ça, le registre GDTR est chargé avec la valeur du pseudo descripteur défini plus loin en tant que gdt.r. notez que ce pseudo descripteur (c'est le nom officiel donné par intel) mesure 48 bits, et est aligné sur 8 octets + 2, car la première partie mesure 16 bits, et la seconde 32 bits. c'est comme ça, ne cherchez pas, intel à dit de faire comme ça, il faut faire comme ça. sauf si on veut ralentir l'instruction LGDT de 2 cycles. ce qui est acceptable mais non désiré, surtout quand on code en assembleur.

bon, la suite:

une fois le registre GDTR chargé avec le pseudo descripteur 48 bits gdt.r, il faut activer le mode protégé.
chose faite en positionnant le bit PE (bit 0) du registre CR0, à 1.
pour ça, on lit une première fois le registre, en le copiant dans eax, ou ailleurs, peu importe.
puis hop, or eax,1, et le bit est mis à 1. magique!!!! et on copie le contenu de eax dans cr0.
le tour est joué, le CPU est en mode protégé, mais il reste une chose primordiale à faire.

charger la partie invisible de CS avec le bon descripteur.
pour ça, un jmp far (saut éloigné en français) vers l'adresse désirée, ici, gdt.cs:activé, et nous voilà enfin en mode protégé, pour de vrai.
le reste, c'est de l'initialisation de registres, on charge le segment de données avec le bon descripteur.
on pointe vers la mémoire vidéo en mode texte.
puis on écrit "bonjour", parce qu'on est polit.

et voilà.
si vous voulez tester ce code, de multiples moyens s'offrent à vous.
vous devez copier le fichier compilé sur le premier secteur du disque de démarrage (disquette, disque dur, clé usb, émulation sur cdrom, image de disque, peu importe) et lancer la machine (virtuelle ou réelle, peu importe).
magique, il s'affiche le message bonjour en haut à gauche de l'écran. c'est joli, ça marche.

et on va passer à la suite, car on s'arrête pas à ça.
au passage, notez que je n'ai pas traduit les commentaires à la fin, j'estime que vous étant mis à l'assembleur, vous n'avez pas peur de trois mots en anglais, en plus, c'est de l'anglais fastoche, écrit pas un français (moi).

pour la macro à la fin, il ne s'agit que d'un message que le compilateur FASM fourni à la compilation, pour dire combien il reste d'octets, et combien d'octets sont utilisés. donc, normalement, avec ce code, vous voyez ça:

19Eh libre bytes
060h used bytes

ce qui veut dire que le code n'utilise que 96 octets (c'est énorme) et que vous avez encore 414 octets dans le secteur de boot pour vous amuser. vérification:
un secteur = 512 octets.
le dernier word (offset 510) est utilisé pour le mot magique. 0AA55h
il reste bien 510 octets pour travailler.
bien évidement, il n'y à pas de table de partition, ça sert à rien ce genre de chose, surtout quand on n'aime pas windows et linux.


to be continued
__________________
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
Vieux 16/03/2011, 23h46   #2
bifur
Membre habitué
 
passe le balais et l'aspirateur
Inscription : mars 2008
Messages : 111
Détails du profil
Informations personnelles :
Âge : 28

Informations professionnelles :
Activité : passe le balais et l'aspirateur

Informations forums :
Inscription : mars 2008
Messages : 111
Points : 126
Points : 126
bravo! encore 2 sujets dans cette section et vous aurez initié plus de la moitié des sujets

par contre je déconseillerait aux créateur d'os de mettre le passage en mode protégé directement dans le premier secteur car on ne peut plus bénéficier des fonction du dos après avoir passer en mode protégé, ce qui est utile si on veut charger d'autre secteurs en mémoire

sauf si bien sur on veut faire du flat real mode, c'est a dire repasser en mode réel après avoir chargé les selecteurs de segment avec un segment de donnée de 4Go, ce qui permet d'avoir un mode avec les fonction du dos et l'accès total a la mémoire
bifur est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2011, 00h25   #3
edfed
Membre chevronné
 
Avatar de edfed
 
être humain
Inscription : décembre 2007
Messages : 471
Détails du profil
Informations professionnelles :
Activité : être humain

Informations forums :
Inscription : décembre 2007
Messages : 471
Points : 619
Points : 619
Ce n'est qu'un début cher ami.

Effectivement, je ne l'ai pas précisé, mais ce petit code n'a qu'un seul but, montrer que c'est très simple de passer au mode protégé.

Evidement, pour exploiter ce mode à fond, c'est tout autre chose, et nécessite plusieurs milliers de lignes de code... ce qui sort littéralement du cadre de la section contribuez, et passe dans la section projets limite commerciaux ou professionnels.

Pour ce qui est du chargement de secteurs en mode protégé, si le lecteur est en IDE, il est tout à fait possible d'utiliser le mode PIO pour charger un nombre limité de secteurs, en atendant d'avoir le pilote DMA requis pour des chargements plus rapides et performants.

Sinon sachez toutefois que sur les PC récents (après 2005) il y a la présence quasi systématique de l'extension de l'interruption bios INT 13H, qui permet de faire une lecture de disque en ... LBA64 (et non pas seulement 28).
__________________
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
Vieux 17/03/2011, 10h06   #4
bifur
Membre habitué
 
passe le balais et l'aspirateur
Inscription : mars 2008
Messages : 111
Détails du profil
Informations personnelles :
Âge : 28

Informations professionnelles :
Activité : passe le balais et l'aspirateur

Informations forums :
Inscription : mars 2008
Messages : 111
Points : 126
Points : 126
tient je ne savait pas que les bios font le LBA64! bonne nouvelle, faut que je me documente la dessus

la doc que je possède ne me permet d'adresser que du LBA48 (ce qui fait des disque de 130 000To tout de même) faut que j'avoue que je me sui contenté de réaliser la programmation d'un mode PIO LBA28

pour finir ue petite question:
- j'avait comprit que le mode ultra DMA des controlleurs ATA n'uttilisait pas le puce DMA qui était uttilisé jadis par le controlleur disquette, est ce que j'aurait mal comprit?
bifur est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2011, 15h48   #5
edfed
Membre chevronné
 
Avatar de edfed
 
être humain
Inscription : décembre 2007
Messages : 471
Détails du profil
Informations professionnelles :
Activité : être humain

Informations forums :
Inscription : décembre 2007
Messages : 471
Points : 619
Points : 619
je ne me suis jamais penché sur du DMA.

ce que je sais, c'est que le contrôleur UDMA existe et est une version améliorée du contrôleur DMA.

le contrôleur DMA est un des casses tête du PC.
__________________
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
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 16h33.


 
 
 
 
Partenaires

Hébergement Web