Precedent | Sommaire | Suivant

2. Realiser un secteur de boot

2.1 Qu'est-ce qu'un secteur de boot ?

Un secteur de boot est un programme situe sur le premier secteur d'une unite de stockage ou d'une partition et qui est charge au demarrage du PC. Le programme de ce secteur a en principe pour tache de charger un noyau en memoire et de l'executer. Ce noyau peut etre present au depart sur une disquette, un disque dur, une bande ou tout autre support magnetique. Ce tutorial detaille ce qui se passe quand on boote sur disquette mais les principes expliques ici restent valables pour tout autre support.

2.2 Charger un secteur de boot en memoire

Au demarrage, le PC initialise et teste le processeur et les peripheriques. Cette phase est le "Power On Self Test" (POST).
Ensuite, le PC execute un programme en ROM, le BIOS, qui va essayer de lire et de charger en memoire le premier secteur de boot d'une unite de disque : le "Master Boot Record" (MBR). Si un MBR est trouve sur la disquette dans le lecteur, il est charge en memoire a l'adresse 0000:7C00. Sinon, le BIOS cherche un MBR sur une autre unite de stockage (disque dur, cdrom, etc.). Une fois que le MBR est charge en memoire, le BIOS passe la main au petit programme qu'il contient.
Le MBR contient un programme mais aussi des donnees. Parmi celles-ci, il y a la table des partitions. Cette table contient des informations sur les partitions du disque (ou elles commencent, leur taille, etc.). Un MBR standard cherche sur la table des partitions une partition active, puis, si une telle partition existe, il charge le secteur de boot de cette partition en 0000:7C00. C'est souvent ce deuxieme secteur de boot qui charge le noyau et lui donne la main.
Par exemple, sous Linux, c'est assez complique car il faut souvent charger trois secteur de boot pour pouvoir demarrer le noyau d'un systeme d'exploitation (possibilite de multi-boot). Le MBR est tout d'abord charge au demarrage. Si une partition active est detectee, le secteur de boot de cette partition est charge puis execute (on a donc charge un deuxieme secteur de boot). Ce secteur contient le programme "LILO" qui, d'une facon interactive, va charger un troisieme secteur de boot lie au systeme choisi par l'utilisateur. Ce dernier secteur va charger puis de lancer un noyau.

2.3 Un secteur de boot qui affiche un message

Nous allons creer un secteur de boot qui ne fait qu'afficher un message. Voici le code d'un programme tres simple qui affiche un message de bienvenue :

	prog01 :
	--------
	[BITS 16]	; indique a nasm que l'on travaille en 16 bits
	[ORG 0x0]
		
	; initialisation des segments en 0x07C0
		mov ax,0x07C0
		mov ds,ax
		mov es,ax
		mov ax,0x8000	; stack en 0xFFFF
		mov ss,ax
		mov sp, 0xf000
	
	; affiche un msg
		mov si,msgDebut
		call afficher
	
	
	end:
		jmp end
	
	
	;--- Variables ---
	msgDebut	db	"Hello world !",13,10,0
	;-----------------
	
	;---------------------------------------------------------
	; Synopsis: Affiche une chaine de caracteres se terminant par 0x0
	; Entree:   DS:SI -> pointe sur la chaine a afficher
	;---------------------------------------------------------
	afficher:
		push ax
		push bx
	.debut:
		lodsb		; ds:si -> al
		cmp al,0	; fin chaine ?
		jz .fin
		mov ah,0x0E	; appel au service 0x0e, int 0x10 du bios
		mov bx,0x07	; bx -> attribut, al -> caractere ascii
		int 0x10
	        jmp .debut
	
	.fin:
		pop bx
		pop ax
		ret
	
	
	;--- NOP jusqu'a 510 ---
	times 510-($-$$) db 144
	dw 0xAA55

Que fait exactement ce programme ?

On indique tout d'abord que l'on travaille sur 16 bits pour le codage des instructions et des donnees, c'est le mode par defaut. Ceci n'est pas encore le debut du programme, c'est juste une directive de compilation pour que l'executable obtenu soit bien sur 16 bits et pas sur 32 bits.
	[BITS 16]	; indique a nasm que l'on travaille en 16 bits
On commence par initialiser les registres 'ds' et 'es'. Ces deux registres du processeur indiquent la zone memoire ou se situe le segment de donnees. Il faut les initialiser de facon a ce que le segment de donnees debute en 0x7C00, puisque c'est l'adresse ou est charge le secteur de boot en memoire.
	; initialisation des segments en 0x07C0
	mov ax,0x07C0
	mov ds,ax
	mov es,ax
Ensuite on initialise le segment de pile (ss) et le pointeur de pile (sp) en faisant commencer la pile en 0x8F000 et en la faisant finir en 0x80000.
	mov ax,0x8000	; stack en 0xFFFF
	mov ss,ax
	mov sp, 0xf000
On a donc :
- la pile qui commence en 0x8F000 et finit en 0x80000 ;
- le segment de donnees qui commence en 0x07C00 et finit en 0x17C00 ;
- le secteur de boot charge en 0x07C00 et qui finit en 0x07CFF.
Une fois les principaux registres initialises, la fonction 'afficher' est appelee. Elle affiche le message pointe par 'msgDebut'. Cette fonction fait appel au service 0x0e de l'interruption logicielle 0x10 du bios qui permet d'afficher un caractere a l'ecran en precisant ses attributs (couleur, luminosite...). Il aurait ete possible d'ecrire un message a l'ecran en se passant de cette facilite offerte par le BIOS mais cela aurait ete beaucoup moins simple a realiser. Patience !
	; affiche un msg
	mov si,msgDebut
	call afficher
Une fois le message affiche, le programme boucle et ne fait plus rien.
	end:
		jmp end
En fin de fichier, on definit les variables et les fonctions utilisees dans le programme. La chaine de caractere affichee au demarrage a pour nom 'msgDebut' :
	msgDebut	db	"Hello world !",13,10,0
Ensuite, la fonction 'afficher' est definie. Elle prend en argument une chaine de caracteres pointee par les registres DS et SI. DS correspond a l'adresse du segment de donnees et SI est un deplacement par rapport au debut de ce segment (un offset).
La chaine de caractere passee en argument doit se terminer par un octet egal a 0 (comme en C).
A la fin du fichier, il y a la directive de compilation suivante :
	;--- NOP jusqu'a 510 ---
	times 510-($-$$) db 144
	dw 0xAA55
Cette directive ajoute du bourrage sous forme d'octets a zero puis le mot 0xAA55 afin que le binaire genere fasse 512 octets. Le mot 0xAA55 en fin de secteur est une signature pour que celui-ci soit reconnu comme etant un MBR valide.

2.4 La pratique : compiler et tester un programme de secteur de boot

Le programme est ecrit dans un fichier qui s'appelle "bootsect.asm". Pour le compiler avec nasm et obtenir le binaire "bootsect", il faut executer la commande suivante :
	$ nasm -f bin -o bootsect bootsect.asm

Pour lancer le secteur de boot, il faut copier le binaire sur une disquette :

	$ dd if=bootsect of=/dev/fd0

Ensuite il faut rebooter sa machine avec cette disquette inseree. C'est tres penible car un PC fait tout un tas de tests plus ou moins longs au demarrage et les possibilites de debogage sont tres limitees. Heureusement, il existe un emulateur de PC qui tourne sur un tres grand nombre de plateformes : "bochs" .
Cet emulateur est distribue avec une documentation claire et je vous invite a l'essayer.