C kernel – Fonctionne bien sur une machine virtuelle mais pas sur un ordinateur réel?

Je fabrique un kernel C de base. (Chargé par un programme d’assemblage) Je le comstack avec un compilateur croisé i686-elf pour windows. Mon code C est comme suit:

void cls(); void drawhappy(); void main(){ char *vidptr = (char *)0xb8000; cls(); drawhappy(); } void cls(){ char *vidptr = (char *)0xb8000; unsigned int j = 0; while(j < 80*2*25){ vidptr[j] = ' '; vidptr[j+1] = 0x07; j = j+2; } } void drawhappy(){ char *vidptr = (char *)0xb8000; const unsigned int linewidth = 80*2; vidptr[3] = 0xa7; vidptr[5] = 0xa7; vidptr[7] = 0xa7; vidptr[9] = 0xa7; vidptr[1+linewidth] = 0xa7; vidptr[5+linewidth] = 0xa7; vidptr[7+linewidth] = 0xa7; vidptr[11+linewidth] = 0xa7; vidptr[1+linewidth*2] = 0xa7; vidptr[3+linewidth*2] = 0xa7; vidptr[5+linewidth*2] = 0xa7; vidptr[7+linewidth*2] = 0xa7; vidptr[9+linewidth*2] = 0xa7; vidptr[11+linewidth*2] = 0xa7; vidptr[1+linewidth*3] = 0xa7; vidptr[5+linewidth*3] = 0xa7; vidptr[7+linewidth*3] = 0xa7; vidptr[11+linewidth*3] = 0xa7; vidptr[1+linewidth*4] = 0xa7; vidptr[11+linewidth*4] = 0xa7; vidptr[3+linewidth*5] = 0xa7; vidptr[5+linewidth*5] = 0xa7; vidptr[7+linewidth*5] = 0xa7; vidptr[9+linewidth*5] = 0xa7; } 

En bochs, cela me donne le résultat attendu: Yay Et si j’utilise bootice pour écrire le fichier bin dans le secteur de démarrage et l’exécuter en tant que machine virtuelle sur virtualbox, cela fonctionne également. Mais si je démarre à partir de la clé USB, cela devient un peu fou, puis un symbole étrange apparaît dans le coin inférieur droit de mon écran. (Pas de capture d’écran car je ne peux évidemment pas) J’ai un processeur i7-3770K. Pourquoi cela arrive-t-il?

EDIT: Voici mon code d’assemblage:

 [org 0x7c00] KERNEL_OFFSET equ 0x1000 mov [BOOT_DRIVE], dl mov bp, 0x9000 mov sp, bp mov bx, MSG_REAL_MODE call print_ssortingng call load_kernel call switch_to_pm jmp $ %include "C:/Users/Aaron/Desktop/CODE_OS/print_ssortingng.asm" ; load DH sectors to ES:BX from drive DL disk_load: push dx mov ah, 0x02 mov al, dh mov ch, 0x00 mov dh, 0x00 mov cl, 0x02 int 0x13 jc disk_error pop dx cmp dh, al jne disk_error ret disk_error: mov bx, DISK_ERROR_MSG call print_ssortingng jmp $ DISK_ERROR_MSG: db "Disk read error!", 0 %include "C:/Users/Aaron/Desktop/CODE_OS/print_ssortingng_pm.asm" %include "C:/Users/Aaron/Desktop/CODE_OS/switch_to_pm.asm" ; GDT gdt_start: gdt_null: ; the mandatory null descriptor dd 0x0 dd 0x0 gdt_code: ; the code segment descriptor dw 0xffff ; limit dw 0x0 ; base db 0x0 db 10011010b db 11001111b db 0x0 gdt_data: dw 0xffff dw 0x0 db 0x0 db 10010010b db 11001111b db 0x0 gdt_end: gdt_descriptor: dw gdt_end - gdt_start - 1 dd gdt_start CODE_SEG equ gdt_code - gdt_start DATA_SEG equ gdt_data - gdt_start [bits 16] load_kernel: mov bx, MSG_LOAD_KERNEL call print_ssortingng mov bx, KERNEL_OFFSET mov dh, 15 mov dl, [BOOT_DRIVE] call disk_load ret [bits 32] BEGIN_PM: mov ebx, MSG_PROT_MODE call print_ssortingng_pm call KERNEL_OFFSET jmp $ BOOT_DRIVE db 0 MSG_REAL_MODE db 'Started in 16-bit Real Mode',0 MSG_PROT_MODE db 'Successfully booted to 32-bit Protected Mode',0 MSG_LOAD_KERNEL db "Loading Kernel...",0 times 510-($-$$) db 0 ; Pad the boot sector out with zeros dw 0xaa55 ; Last two bytes form the magic number 

(Print-ssortingng.asm n’imprime que des chaînes, switch_to_pm.asm passe en mode protégé et print_ssortingng_pm.asm imprime des chaînes en mode protégé.)

Vous n’initialisez pas les registres de segments. Essayez de changer le début de votre secteur de démarrage en quelque chose comme ceci:

 xor ax, ax mov bp, 0x9000 mov ds, ax mov es, ax mov ss, ax ; disables interrupts until the end of the next instruction mov sp, bp mov [BOOT_DRIVE], dl