Hi. ich hab mir einen kleinen Kernel geschrieben (hab noch so gut wie keine Ahnung von allem), der von GRUB gebootet werden soll und danach in den Protected Mode springt. Leider startet der PC, nachdem ich meinen Kernel ausgewählt habe, immer neu. Virtual PC meldet einen unbehebbaren Prozessorfehler. Bootloader ist GRUB 0.97. Hier mein Code:
; --------------- MULTIBOOTHEADER FÜR GRUB ---------------
_mbh:
Multiboot_Magic equ 0x1BADB002
Multiboot_Flags equ 0x00010000
Multiboot_Checksum equ -Multiboot_Magic-Multiboot_Flags
Multiboot_HeaderOffset equ 0x00100000+_mbh
dd Multiboot_Magic
dd Multiboot_Flags
dd Multiboot_Checksum
dd Multiboot_HeaderOffset
dd 0x00100000
dd 0x00100000+_end
dd 0x00100000+_end
dd 0x00100000+_start
; --------------- KERNEL ---------------
_start:
; jetzt gehen wir in den Protected Mode
jmp afterdeskriptor ; jetzt werden die drei wichtigen Deskriptoren erzeugt
NULL_Desc:
dd 0
dd 0
CODE_Desc: ; ein Code-Deskriptor für den Kernel
dw 0xFFFF
dw 0
db 0
db 0x9A
db 0xCF
db 0
DATA_Desc: ; und noch einen Data-Deskriptor für den Kernel
dw 0xFFFF
dw 0
db 0
db 0x92
db 0xCF
db 0
gdt: ; Daten für die Global Deskriptor Table
Limit dw 0
Base dd 0
afterdeskriptor: ; alle Deskriptoren erzeugt und übersprungen, also gehts hier weiter
; Protected Mode, wir kommen!
cli ; keine Interrupts
mov eax, cs
mov ds, ax
; jetzt müssen wir den Deskriptor ändern, weil wir den Kernel nicht mit Code-Segment+16Bit-Adresse erreichen können
shl eax, 4
mov [CODE_Desc+2], ax
mov [DATA_Desc+2], ax
shr eax, 16
mov [CODE_Desc+4], al
mov [DATA_Desc+4], al
; Jetzt wird die GDT mit Daten gefüllt:
mov eax, cs
shl eax, 4
add eax, NULL_Desc
mov [Base], eax
mov [Limit], WORD gdt - NULL_Desc - 1
; GDT wird geladen
lgdt [gdt]
; Jetzt gehts in den Protected Mode
mov eax, cr0 ; cr0 in eax laden
or eax, 1 ; Das erste Bit auf 1 setzen
mov cr0, eax ; cr0 zurückschreiben
; jetzt noch den FAR JUMP, cs laden und Prefetch leeren
db 0xea
dw PMODE
dw 0x8
[bits 32] ; Die 16-Bit vorbereitungen sind fertig, jetzt gehen wir auf 32 Bit
;%macro PM_Print 4 ; x, y, zeichen, attribut ; unser Macro zum schreiben
; ;;;;;;;mov ax, %2*80+%1 ;offset errechnen
; mov ax, %2
; mov bx, 80
; mul bx
; add ax, %1
; add ax, 0xB8000
; mov bx, %3
; or bx, %4
; mov [ax], bx
;%endmacro
PMODE: ; hierhin wird geJUMPt
mov WORD [CODE_Desc+2], 0 ; Deskriptoren wieder zurücksetzen
mov WORD [DATA_Desc+2], 0
mov WORD [CODE_Desc+4], 0
mov WORD [DATA_Desc+4], 0
mov eax, 2 ; Index 2 der GDT auswählen (also 3. Eintrag)
shl eax, 3 ; Im Selektor beginnt der Index erst ab Bit 3
mov ds, ax
mov es, ax
mov ss, ax
mov eax, 0
mov fs, ax
mov gs, ax ; FS und GS auf NULL Deskriptor zeigen lassen
mov gs, ax
mov esp, 0x1FFFFF ; esp (stack) auf 2 MB setzen
; weil wir den Deskriptor verändert haben, müssen wir noch einmal FAR JUMPen, damit alles richtig geladen wird
jmp 0x8:0x10000 + main
main: ; wir sind endlich im MAIN-Teil des Kernels angekommen! PARTY!!!
;PM_Print 40, 10, 72, 0x14
;jmp main
jmp main
_end:
achja: mein Makro für die Textausgabe funktioniert auch nicht. Der Code lässt sich dann nicht assemblieren. NASM meldet irgendwas mit invalid segmen/addres oder so. Weiß da jemand warum?