Der Code schon wieder. Ich weiß nicht, warum die Leute glauben, dass sie in der GDT rumfummeln müssen ... Ich und der Autor des Tutorials, aus dem der Code stammt, wissen warum man das macht, und keiner von uns beiden hat Lust das zu erklären. Einer von uns beiden hätte das besser erklären müssen. (Ich bin das nicht.) Deswegen geht das immer schief, wenn die Leute den Code kopieren.
Ich hab mal deine kernel.asm frisiert. Die funktioniert bei mir in qemu.
Die entscheidenen Unterschiede sind, dass ich überall im 16-Bit Code start abziehe, und damit praktisch auf relative Adressierung umsteige.
Dann generiert der Assembler keine globalen Referenzen mehr, weil er das selbst berechnen kann, und der Linker stört sich daran nicht. Das funktioniert, weil der Ladeoffset (=bx) 0 ist. Der Sprung in den Protected-Mode muss dann ein 32-Bit-Sprung sein (db 0x66, ...), weil das Ziel an einer Adresse über 0x10000 liegt, also nicht mehr mit 16-Bit darstellbar ist.
[GLOBAL start]
start:
[BITS 16]
cli
; <------------- unfug gelöscht
mov eax, cs
shl eax, 4
add eax, NULL_Desc-start ; <-------------
mov [Base-start], eax ; <-------------
mov [Limit-start], word gdt - NULL_Desc -1 ; <-------------
lgdt [gdt-start] ; <-------------
mov eax, cr0
or eax, 1
mov cr0, eax
db 0x66 ; <-------------
db 0xea
dd PMODE-start+0x10000 ; <-------------
dw 0x8
[BITS 32]
PMODE:
mov eax, 2
shl eax, 3
mov ds, ax
mov ss, ax
mov es, ax
mov eax, 0
mov fs, ax
mov gs, ax
mov esp, 0x1FFFFF
jmp 0x8:PMODE2 ; <-------------
PMODE2:
[EXTERN main]
call main
[GLOBAL kernelerror]
kernelerror:
mov byte [0xB8000], 'K'
mov byte [0xB8001], 0x07
mov byte [0xB8002], 'e'
mov byte [0xB8003], 0x07
mov byte [0xB8004], 'r'
mov byte [0xB8005], 0x07
mov byte [0xB8006], 'n'
mov byte [0xB8007], 0x07
mov byte [0xB8008], 'e'
mov byte [0xB8009], 0x07
mov byte [0xB800A], 'l'
mov byte [0xB800B], 0x07
mov byte [0xB800C], 'e'
mov byte [0xB800D], 0x07
mov byte [0xB800E], 'r'
mov byte [0xB800F], 0x07
mov byte [0xB8010], 'r'
mov byte [0xB8011], 0x07
mov byte [0xB8012], 'o'
mov byte [0xB8013], 0x07
mov byte [0xB8014], 'r'
mov byte [0xB8015], 0x07
endless_loop:
cli
hlt
NULL_Desc:
dd 0
dd 0
CODE_Desc:
dw 0xFFFF
dw 0
db 0
db 10011010b
db 11001111b
db 0
DATA_Desc:
dw 0xFFFF
dw 0
db 0
db 0x92
db 0xCF
db 0
gdt:
Limit dw 0
Base dd 0
Damit der Code funktioniert, musst du im Linkerskript phys auf 0x10000 setzen. Mich wundert, dass das setzen der Ladeadresse funktioniert. Ich würde eher die Linkadresse setzen, also so:
OUTPUT_FORMAT("binary")
ENTRY(start)
SECTIONS
{
. = 0x10000;
.text : {
code = .;
*(.text)
*(.rodata)
. = ALIGN(0);
}
.data :
{
data = .;
*(.data)
. = ALIGN(0);
}
.bss :
{
bss = .;
*(.bss)
. = ALIGN(0);
}
end = .;
}