J'essaye d'écrire un chargeur de démarrage en utilisant NASM et par conséquent, j'ai trouvé OSDEV extrêmement utile. Toutefois, quelque part dans le processus de configuration de la pagination, du chargement de mon GDT ou de la transition (im venant directement du mode réel), une erreur entraîne le redémarrage de l'ordinateur. J'ai basé mon code sur le Long mode OSDEV article. Voilà ce que j'ai ce qui est important à la question:Configuration de la pagination pour le mode réel sur le commutateur de mode 64 bits
TDG
gdt_start:
.gdt_null: equ $-gdt_start ; mandatory null descriptor
dw 0
dw 0
db 0 ; define double word
db 0
db 0
db 0
.gdt_code: equ $-gdt_start ; code segment
; base = 0x0, limif = 0xffff
; 1st flags: (present)1 (privilege)00 (descriptor type)1 -> 1001
; type flags: (code)1 (conforming)0 (readable)1 (accessed)0 -> 1010
; 2nd flags: (granularity)1 (32 bit default)1 (64 bit seg)0 (AVL)0 -> 1100
dw 0 ; limit (0-15)
dw 0 ; base (0-15)
db 0 ; base (16-23)
db 10011010b ; 1st/type flags
db 00100000b ; 2nd flags, limit (16-19)
db 0 ; base (bits 24-31)
.gdt_data: equ $-gdt_start ; data segment descriptor
; type flags (code)0 (expand down)0 (writable)1 (accessed)0 -> 0010
dw 0 ; limit
dw 0 ; base
db 0 ; base
db 10010010b ; 1st/type flags
db 00000000b ; 2nd flags, limit
db 0 ; base
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; size of GDT
dq gdt_start
CODE_SEG equ gdt_start.gdt_code
DATA_SEG equ gdt_start.gdt_data
Paging et interrupteur:
%include "gdt.ns"
;test/enable A20 line
call test_a20
fin:
cmp ax, 1
je enabled
call enable_A20
enabled:
;switch
call switch_to_lm
jmp $
switch_to_lm:
;
; SET UP PAGING!!!!!
;
;no previous paging defined so the below code is unnecessary
;mov eax, cr0
;and eax, 01111111111111111111111111111111b
;mov cr0, eax
;clear tables
mov edi, 0x1000
mov cr3, edi
xor eax, eax
mov ecx, 4096
rep stosd
mov edi, cr3
;set up new tables
mov DWORD [edi], 0x2003
add edi, 0x1000
mov DWORD [edi], 0x3003
add edi, 0x1000
mov DWORD [edi], 0x4003
add edi, 0x1000
mov ebx, 0x00000003
mov ecx, 512
.setEntry:
mov DWORD [edi], ebx
add ebx, 0x1000
add edi, 8
loop .setEntry
;enable PAE bit in CR4
mov eax, cr4
or eax, 1<<5
mov cr4, eax
;switch from REAL MODE
;set long mode bit
mov ecx, 0xc0000080
rdmsr
or eax, 1<<8
wrmsr
;enable paging
mov eax, cr0
or eax, 1<<31
mov cr0, eax
lgdt [gdt_descriptor]
jmp CODE_SEG:init_lm
[bits 64]
init_lm:
cli
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov ebp, 0x90000
mov esp, ebp
call BEGIN_LM
Mon code pour tester A20:
test_a20:
pushf
push ds
push es
push di
push si
cli
xor ax, ax
mov es, ax
not ax
mov ds, ax
mov di, 0x0500
mov si, 0x0510
mov al, byte [es:di]
push ax
mov byte [es:di], 0x00
mov byte [ds:si], 0xff
cmp byte [es:di], 0xff
pop ax
mov byte [ds:si], al
pop ax
mov byte [es:di], al
mov ax, 0
je test_exit
mov ax, 1
test_exit:
pop si
pop di
pop es
pop ds
popf
jmp fin
Veuillez montrer un exemple minimal complet vérifiable. –
@MichaelPetch La seule autre chose que je fais est de vérifier cpuid/longmode comme mentionné par l'article OSDEV et j'active la ligne A20 si elle n'est pas déjà activée. Le problème se produit lorsque j'appelle l'étiquette 'switch_to_lm'. Quelle "réponse varifiable complète minimale" voulez-vous? – Mike
La quantité minimale et complète de code qui permet à quiconque de reproduire le problème, y compris les commandes utilisent pour lier/compiler/assembler etc Regardant ça je ne vois pas le problème, et je suis très actif dans les questions OSDEV sur SO. Les fois où je ne demande pas un exemple complet minimal, je passe des heures inutiles et des dizaines de commentaires pour découvrir que des choses sans rapport avec le code présenté étaient un problème. Si vous deviez placer votre code sur Github ou m'envoyer une archive de vos fichiers par email, je pourrais probablement tester votre problème plus rapidement. Mon adresse e-mail est [email protected] –