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 136 137 138 139 140
|
; BOOT 0.1, passage en mode protégé et retour au monde réel :)
; (c) 2010 by Paul TOTH <tothpaul@free.fr>
; à compiler sous FASM
; adresse de chargement du secteur BOOT par le BIOS
ORG $7C00
PUSH CS
POP DS
; Configuration des selecteurs
MOV BX,GDT
LGDT [BX]
; sauvegarde des segments 16bits
PUSH DS
PUSH CS
; basculer en mode protégé
MOV EAX,CR0
OR AL,1
MOV CR0,EAX
; ATTENTION ici les valeurs des registres de segments sont invalides.
; on hérite cependant des attributs du mode réel et le programme
; continue à fonctionner. Mais il faut dorénavant leur donner des offset
; dans la GDT et non plus des segments du mode réel !
; passer CS sur un description 32bits
JMP FAR $08:CODE32 ; $08 est un offset dans la GDT (GDT_08)
CODE32:
USE32 ; préciser à FASM que l'adressage a changé
; faire pointer ES et DS sur DATA32
MOV AX,$10 ; $10 est un offset dans la GDT (GDT_10)
MOV ES,AX
MOV DS,AX
; afficher un message en adressage linéaire 32bits
MOV ESI, msg1
MOV EDI, $B8000 ; mémoire vidéo
MOV AH,$70 ; attribut noir sur blanc (en fait gris)
MOV CX, msg1_length
Next32:
LODSB ; AL = [DS:ESI++]
STOSW ; [ES:EDI] = AX; EDI += 2
LOOP Next32
; revenir à un adressage 16bits
JMP FAR $18:CODE16 ; $18 est un offset dans la GDT (GDT_18)
CODE16:
USE16 ; préciser à FASM que l'on est de nouveau en adressage 16bits
; retour en mode réel
MOV EAX,CR0
AND AL,254
MOV CR0,EAX
; restaurer CS (qui est sur la pile) avec sa valeur initiale (et non $18)
PUSH SetCS
RETF
SetCS:
; restaurer DS (qui est sur la pile)
POP DS
; appel au BIOS, preuve du fonctionnement en mode réel
MOV SI,msg2
MOV CX,msg2_length
Next2:
LODSB
MOV AH,$0E
MOV BX,$70
INT $10 ; on fait appel au BIOS et non au DOS qui n'est pas chargé !!!
LOOP Next2
; boucle éternelle
JMP $
; notre message
msg1 DB 'Hello World !'
; sa longueur
msg1_length = $ - msg1
; Configuration de la GDT (Global Descriptor Table)
; attributs
SIZE_4K = 10000000b ; indique que la taille est exprimée en pages de 4K, sinon ce sont des octets
CODE_32 = 01000000b ; l'adressage se fait en mode 32bits, sinon en 16bits (cf préfix DB 66h)
EXT_SIZE = 00001111b ; bits qui complète la taille pour atteindre 4Gb
; accès
PRESENT = 10000000b ; l'adresse est valide
APP_DESC = 00010000b ; utilisé par un programme
READ_WRITE = 00000010b ; accessible en écriture (DATA)
; accessible en lecture (CODE)
EXEC = 00001000b ; execution autorisée
GDT_00 DW 0
DW 0
DB 0
DB 0
DB 0
DB 0
; CODE32, 4Gb
GDT_08 DW $FFFF ; Taille
DW 0 ; Adresse de base
DB 0 ; Adresse partie haute
DB PRESENT + APP_DESC + READ_WRITE + EXEC ; Attributs
DB SIZE_4K + CODE_32 + EXT_SIZE ; Mode d'accès
DB 0 ; Adresse de base étendue
; DATA32, 4Gb
GDT_10 DW $FFFF ; Taille
DW 0 ; Adresse de base
DB 0 ; Adresse partie haute
DB PRESENT + APP_DESC + READ_WRITE ; Attributs
DB SIZE_4K + CODE_32 + EXT_SIZE ; Mode d'accès
DB 0 ; Adresse de base étendue
; CODE16, 4Gb
GDT_18 DW $FFFF ; Taille
DW 0 ; Adresse de base
DB 0 ; Adresse partie haute
DB PRESENT + APP_DESC + READ_WRITE + EXEC ; Attributs
DB SIZE_4K + EXT_SIZE; Mode d'accès
DB 0 ; Adresse de base étendue
GDT DW $ - GDT_00
DW GDT_00
DW 0
msg2 DB 'Back to real world !'
msg2_length = $ - msg2
; compléter le secteur 0
DB 510 - ($ - $$) DUP(0)
; secteur bootable
DW $AA55 |
Partager