Hallo zusammen,
ich habe da ein kleines Problem. Ich teste mein OS mit Bochs. Das OS ist in einem HD Image. Zunächst habe ich einen "sehr kleinen" Bootloader. Dieser soll den zweiten Sektor laden und dann dort hin springen. Das funktioniert auch wunderbar. Jetzt habe ich folgendes Problem. Den folgenden Kernel schreibe ich in C. Zum compilieren und linken nutze ich gcc/ld. Da ich mich noch nicht im pMode befinde habe ich in der kernel.c die asm direktive .code16gcc benutzt um 16Bit Opcode zu erzeugen. Das funktioniert auch. Was nicht funktioniert ist das schreiben in den Videospeicher bei 0xA8000 (oder 0xB8000 ich glaube aber ersteres, spielt aber auch erstmal keine Rolle in beiden Fällen klappt es nicht). Ein Debug mit Bochs ergibt folgendes. Bei der asm Anweisung mov byte ptr ds:[eax], xx bekomme ich den Fehler:
Bochs: write_virtual_checks(): write beyond limit, r/w
xx ist ein beliebiger Wert, ds ist 0 und eax ist 0xA8000. Ich verstehe nicht warum nun eine solche Fehlermeldung auftritt. Die Adresse müsste doch auch im Realmode addressierbar sein, oder nicht? Ich hoffe ihr könnt ein bisschen Klarheit in die Sache bringen. Danke.
boot.asm
; ----------------------------
; BOOTLOADER
; ----------------------------
[BITS 16]
section .text
extern main
global start
start:
mov eax, 0
mov ebx, 0
mov ecx, 0
mov edx, 0
mov ax, cs
mov ds, ax
mov es, ax
mov esi, 0
mov edi, 0
cli ;Interrupts löschen
mov ax, 0x9000 ;------------------
mov ss, ax ;Stack einrichten
mov sp, 0 ;------------------
sti ;Interrupts zulassen
mov si, loadmsg
call putstr
mov ah, 2
mov al, 1
mov cl, 2
mov ch, 0
mov dh, 0
mov dl, 0x80
mov ebx, 0x00007E00
int 13h
failure: jc failure
jmp 0x7E00
; +----------------------+
; |putstr |
; |----------------------|
; |Funktion: |
; |Gibt String aus |
; |----------------------|
; |si, String |
; +----------------------+
putstr:
lodsb
or al, al
jz short putstrd
mov ah, 0x0E
mov bx, 0x0005
int 10h
jmp putstr
putstrd:
retn
; ------------------------
; Funktionen und Variablen
; ------------------------
loadmsg db "OS wird geladen...",0
times 512-($-$$)-2 db 0
dw 0AA55h
asm(".code16gcc\n");
int main()
{
// Pointer zum Videospeicher
char *video = (char*)0xA8000;
// String zum Ausgeben
char *hello = "Executing Kernel...";
// Zuerst den Speicher leeren
for(video+=4000; video !=(char*)0xA8000 ;video--)
*video=0;
// String ausgeben
while (*hello) {
*video = *hello;
video++;
*video = 0x07;
video++;
hello++;
}
// jetzt wo wir schon im Kernel drin sind, wollen wir auch nicht mehr raus ;)
while (1);
return 0;
}