Textausgabe im Protected Mode
-
Hallo, da bin ich wieder mal. Das mit dem Bootloader hat erolgreich geklappt, danach gehe ich erfolgreich (zumindest im Bochs...) in den Protected Mode und boote den C Kernel. Und ich habe das jetzt extra ins Assembler Forum geschrieben, weil das Problem acuh mit ASM zusammenhängt. Weder mit C noch mit Assembler kann ich Text ausgeben (über den Framebuffer). Außerdem kommt immer in Bochs ein "S" oben links am Bildschirm. Ich bekomme das auch nicht weg. Aber jetzt erstmal den Code:
;bootloader.asm [BITS 16] org 7c00h jmp loader start: cli ; Interrupts ausschalten lgdt [gdtr] ; GDT Pointer laden mov eax,cr0 ; In PMode wechseln, indem das niedrigste or al,1 ; Steuerungsbit von cr0 geändert wird mov cr0,eax ; muss über Umweg über ein anderes Register gemacht werden jmp codesel:PMode ; FarJump zu einer 32-Bit PMode Funktion [BITS 32] PMode: mov ax,datasel ; Segmentregister laden mov ds,ax mov ss,ax mov es,ax mov ss,ax mov fs,ax mov gs,ax mov esp,0x90000 ; Stack aufsetzen jmp codesel:10000h ; Endlosschleife, wird durch weiteren Code ersetzt gdtr: ; Desktiptortabelle dw gdt_end-gdt-1 ; Limit dd gdt ; Basisadresse gdt: dd 0,0 ; Null-Deskriptor codesel equ $-gdt dw 0xFFFF ; Segmentgrösse 0..15 dw 0x0000 ; Segmentadresse 0..15 db 0x00 ; Segmentadresse 16..23 db 0x9A ; Zugriffsberechtigung und Typ db 0xCF ; Zusatzinformationen und Segmentgrösse 16...19 db 0x00 ; Segmentadresse 24..31 datasel equ $-gdt dw 0xFFFF ; Segmentgrösse 0..15 dw 0x0000 ; Segmentadresse 0..15 db 0x00 ; Segmentadresse 16..23 db 0x92 ; Zugriffsberechtigung und Typ db 0xCF ; Zusatzinformationen und Segmentgrösse 16...19 db 0x00 ; Segmentadresse 24..31 gdt_end [BITS 16] loader: cli mov ax, 9000h mov ss, ax mov sp, 0ffffh sti mov ah, 02h ;fest mov al, 19h ;Anzahl mov ch, 00h ;Spur mov cl, 02h ;Sektor mov dh, 00h ;Kopf mov dl, 00h ;Laufwerksnummer mov bx, 1000h mov es, bx ;Segment mov bx, 0000h ;Offset int 13h jmp start times 510-($-$$) db 0 signatur dw 0aa55h;kernel32.asm [Bits 32] extern _main global start start: call _main end: jmp end//kernel.c int main(void) { char *Text = "Welcome to Protected Mode"; char *VideoMem = (char*)0xB8000; while(*Text!=0) { *VideoMem = *Text; VideoMem++; *VideoMem = 7; VideoMem++; Text++; } ende: goto ende; }ich benutze gcc mit dem "ld" linker. Hier das linkerfile:
OUTPUT_FORMAT("binary") INPUT(kernel32.o kernel.o) ENTRY(start) SECTIONS { .text 0x200 : { code = .; _code = .; __code = .; *(.text) . = ALIGN(1); } .data : { data = .; _data = .; __data = .; *(.data) . = ALIGN(1); } .bss : { bss = .; _bss = .; __bss = .; *(.bss) . = ALIGN(1); } end = .; _end = .; __end = .; }ich erzeuge aus der kenrnel32.asm eine kernel32.o, aus der kernel.c eine kernel.o und linke diese zusammen und erzeuge eine kernel.bin. Die bootloader.asm wird als bootlaoder.bin erzeugt. Danach kopiere ich das ganze mit dem Windows-Befehl copy /b bootloader.bin+kernel.bin os.img und schreibe das ganze dann mit RawWrite auf eine Diskette und lass es mit Bochs emulieren.
Bei Bochs klappt es aber noch. Bei meinem AMD Athlon X2 3600+ klappt das ganze aber nicht (schätzte der sprung in den pmode). Ich kann auch kein Buchstabe mit:mov byte [ds:0B8000h], 'A'ausgeben. Kann mir jemand helfen?
-
Entschuldigung. Ich meine:
mov byte [0xb8000], 65
-
Sieht so grundsaetzlich erstmal nicht ganz falsch aus.
Also im Bochs klappt die Ausgabe, beim richtigen PC nicht mehr?
An welcher Stelle versuchst du denn sonst die Ausgabe mit Assembler?Was noch direkt auffaellt, da zitiere ich mich mal aus einem deiner aelteren Themen selbst:
Nobuo T schrieb:
Zum Bootloader:
Fehlerbehandlung fehlt. Kann gut sein, dass das Lesen mit int 0x13, Funktion 2 fehlschlaegt. In diesem Fall solltest du es noch einige Male versuchen. Vor jedem Lesen sollte das Laufwerk mit int 0x13, Funktion 0 zurueckgesetzt werden.Auch wirklich ekelig ist der byte-aligned stack (sp=0xffff).
Sowas macht man einfach nicht.
Sieh mal mindestens zu, dass der zumindest immer word-aligned ist, besser noch dword aligned. Da wuerde es sich zB. anbieten sp fuer den Real auf 0 zu setzen. Das cli/sti um die Stack-Initialisierung ist uebrigens im vergangenen Monat auch nicht wirklich sinnvoller geworden...Zumindest unschoen: du setzt hintereinander die ganzen 8Bit-Register mit Konstanten. Das blaest nicht nur den Code unnoetig auf (sowohl Quellcode als auch die binaries nach dem Assemblieren), sondern ist auch noch langsam und laesst sich ja nun wirklich leicht vermeiden.
; zB. statt mov ah, 02h ;fest mov al, 19h ;Anzahl ;besser: mov ax, 0219h ; Funktion 2 - lesen; Anzahl Sektoren ;oder wenn es wie im Bootloader um Platz geht statt mov dh, 00h ;Kopf mov dl, 00h ;Laufwerksnummer ; besser xor dx, dx
-
Nein im Bochs klappt die Ausgabe nicht, also dieses "S" erscheint. Beim echten Neustart stürtzt er ab.
-
ok, dann waere mein Vorschlag: Mach erstmal deinen Code etwas ordentlich und schau dir dann mal mit dem Bochs Debugger an, was da passiert.
-
Es kommt immer nach:
jmp codesel:10000h
-
Also Bochs schmeisst beim jump eine Exception?
Ok... dann noch Folgendes:
Achte darauf, zur Adressierung beim lgdt-Befehl ein initialisiertes Segmentregister zu benutzen (ds fuer RM initialisieren).
Dein gdt-limit ist evtl. 1 zu klein.
-
Es hat jetzt geklappt!
Danke ich werde auf sauberen Code achten