- .386p
- .dosseg
-
- assume cs:pmode,ds:pmode,ss:pmode,es:pmode,fs:nothing,gs:nothing
-
-
- pmode segment public use32
-
- startGDT: ;la GDT
- null dw 0,\ ;le descripteur nul
- 00h
- db 00h,\
- 00000000b,\
- 00000000b,\
- 00h
- code32 dw 00ffffh,\ ;le descripteur du segment de code
- 00h
- db 00h,\
- 10011010b,\
- 11001111b,\
- 00h
- data32 dw 00ffffh,\ ;le descripteur du segment de données/pile
- 00h
- db 00h,\
- 10010010b,\
- 11001111b,\
- 00h
- endGDT:
-
- pGDT dw endGDT-startGDT-1 ;le pointeur sur la GDT
- dd 0
-
- startup: ;point d'entrée du programme
- mov eax,pmode ;initialise le selecteur du segment de données
- mov ds,eax
-
- mov eax,ds ;initalise du pointeur sur la GDT
- shl eax,4
- add eax,startGDT
- mov dword ptr [pGDT+02h],eax
-
- mov eax,pmode ;sauvegarde le segment courant
- mov gs,eax
-
- cli ;désactive les interruptions masquables
-
- in eax,70h ;désactive les NMIs
- or eax,10000000b
- out 70h,eax
-
- mov eax,cr0 ;teste la présence du mode protégé
- test eax,00000001b
- jnz exit ;génère une erreur (une sortie directe du programme) si le CPU est déjà en PMODE
-
- lgdt fword ptr [pGDT] ;charge la GDT en mémoire
-
- or eax,00000001b ;passe en mode protégé
- mov cr0,eax
-
- jmp far ptr entry ;reinitialise la queue d'instructions
-
- entry:
- mov eax,10h ;reinitialise le sélecteur du segment de données
- mov ds,eax
-
- mov ss,eax ;reinitialise le sélecteur du segment de pile
- mov esp,1000000h
-
- mov es,eax ;reinitialise le sélecteur du segment de données supplémentaire
-
- mov eax,cr0 ;repasse en mode réel
- and eax,01100000000000000000000000010000b
- mov cr0,eax
-
- jmp far ptr back ;reinitialise la queue d'instructions
-
- back:
- mov eax,gs ;reinitialise le sélecteur du segment de données
- mov ds,eax
-
- mov ss,eax ;reinitialise le sélecteur du segment de pile
-
- mov es,eax ;reinitialise le sélecteur du segment de données supplémentaire
-
- exit:
- in eax,70h ;réactive les NMIs
- and eax,7fh
- out 70h,eax
-
- sti ;réactive les interruptions masquables
-
- mov eax,4c00h ;rend le contrôle au DOS
- int 21h
-
- pmode ends
-
-
- end startup
.386p
.dosseg
assume cs:pmode,ds:pmode,ss:pmode,es:pmode,fs:nothing,gs:nothing
pmode segment public use32
startGDT: ;la GDT
null dw 0,\ ;le descripteur nul
00h
db 00h,\
00000000b,\
00000000b,\
00h
code32 dw 00ffffh,\ ;le descripteur du segment de code
00h
db 00h,\
10011010b,\
11001111b,\
00h
data32 dw 00ffffh,\ ;le descripteur du segment de données/pile
00h
db 00h,\
10010010b,\
11001111b,\
00h
endGDT:
pGDT dw endGDT-startGDT-1 ;le pointeur sur la GDT
dd 0
startup: ;point d'entrée du programme
mov eax,pmode ;initialise le selecteur du segment de données
mov ds,eax
mov eax,ds ;initalise du pointeur sur la GDT
shl eax,4
add eax,startGDT
mov dword ptr [pGDT+02h],eax
mov eax,pmode ;sauvegarde le segment courant
mov gs,eax
cli ;désactive les interruptions masquables
in eax,70h ;désactive les NMIs
or eax,10000000b
out 70h,eax
mov eax,cr0 ;teste la présence du mode protégé
test eax,00000001b
jnz exit ;génère une erreur (une sortie directe du programme) si le CPU est déjà en PMODE
lgdt fword ptr [pGDT] ;charge la GDT en mémoire
or eax,00000001b ;passe en mode protégé
mov cr0,eax
jmp far ptr entry ;reinitialise la queue d'instructions
entry:
mov eax,10h ;reinitialise le sélecteur du segment de données
mov ds,eax
mov ss,eax ;reinitialise le sélecteur du segment de pile
mov esp,1000000h
mov es,eax ;reinitialise le sélecteur du segment de données supplémentaire
mov eax,cr0 ;repasse en mode réel
and eax,01100000000000000000000000010000b
mov cr0,eax
jmp far ptr back ;reinitialise la queue d'instructions
back:
mov eax,gs ;reinitialise le sélecteur du segment de données
mov ds,eax
mov ss,eax ;reinitialise le sélecteur du segment de pile
mov es,eax ;reinitialise le sélecteur du segment de données supplémentaire
exit:
in eax,70h ;réactive les NMIs
and eax,7fh
out 70h,eax
sti ;réactive les interruptions masquables
mov eax,4c00h ;rend le contrôle au DOS
int 21h
pmode ends
end startup