Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: TPSeverino am 26. May 2004, 20:42
-
Hi,
Ich programmiere seit einiger Zeit mit NASM und habe, nachdem ich das Low-Level-Tutorial gelesen habe, auch ein kleines OS geschrieben. Mein Bootloader funktioniert und lädt den Kernel von Diskette in den Speicher. Nach dem Sprung zum Kernel wird der Code des Kernels auch ausgeführt (der Computer wartet wie vorgesehen auf einen Tastendruck und rebootet anschließend). Das einzige Problem ist, dass die Variablen die ich ausgeben will, nicht auf dem Bildschirm erscheinen! (Im Bootloader hats funktioniert). Nun wurde in allen Tutorial, die ich gefunden habe, ds auf die Segmentadresse gesetzt, an die der Kernel geladen wurde. Also wenn der Kernel bei 1000h:0000h steht, wurde im Kernel immer ds auf 1000h gesetzt. Das führt aber bei mir zu keiner Ausgabe.
Ich habe jetzt schon unzählige Tutorials gelesen und alles mögliche probiert aber meine Strings werden nicht ausgegeben. Was muss ich tun?? Helft mir!! *fleh*
-
du darfst keine variablen aus dem bootloader benutzen, weil bei denen die adressen ja nicht stimmen und dann kommt nichts. alle strings, die du im kernel ausgeben willst, müssen auch da erstellt werden....
-
Aber die Variablen stehen doch im Kernel! das ist ja das ganze Problem
-
dann nimm doch einfach mal den code vom Mag und schau, ob es da geht, wenn nicht, weiß ich es auch nicht. wenns geht, schau doch mal alle register usw. durch, vielleicht wird ja die stringadresse falsch angegeben...
-
ich hab den code 1:1 kopiert und es geht nicht!! (hab ein p4 da sollte es doch gehen oder???)
-
Poste doch einfach mal deinen Code :)
-
Hier ist der Code meines Kernels der sich an 1000h:0000h befindet:
mov ax, 1000h
mov ds, ax
mov es, ax
mov si, welcomemsg
call _putstr
mov si, insertmsg
call _putstr
call _waitforkey
jmp _reboot
; Bildschirm löschen
_clrscr:
mov ah, 0fh
int 10h
mov ah, 00h
int 10h
ret
; auf Tastendruck warten
_waitforkey:
mov ah, 00h
int 16h
ret
; String ausgeben
_putstr:
lodsb
or al,al
jz _putstr_ende
mov ah, 0Eh
mov bh, 00h
mov bl, 07h
int 10h
jmp _putstr
_putstr_ende:
ret
_reboot:
db 0EAh
dw 0000h
dw 0FFFFh
welcomemsg db "Welcome to ...",13,10,0
insertmsg db "Press any key.",13,10,0
-
Kann vielleicht iregndjemand den Code bei sich testen und mir saegn obs funktioniert??? irgendwo muss doch ein fehler sein!!
danke
-
hast du org 0x0 gesetzt? Damit meine ich folgendes:
der Kernelcode liegt in einer Extra-Datei und hat [org 0x00] am Dateianfang stehen, wurde kompiliert und nach den 512 Bytes de bootloaders auf die Diskette geschrieben.
-
also das org 0x00 hat die sache leider auch nicht gelöst ... kann bitte mal kemand meinen code testen und sagen ob er bei ihm funktioniert!? ich bin schon leicht am verzweifeln
-
stell mal bitte alles rein; *zu faul zum suchen des Quelltextes ist* dann test ichs nachher aus ^.^
-
ok, also hier alles in allem (ist alles noch sehr primitiv)
mein Bootloader:
org 7C00h ; Startadresse
_start:
mov ax, 0h
mov es, ax ; Segmenregister setzen
mov ds, ax
; Stack einrichten
cli ; Interrputs verbieten
mov ax, 0x9000 ; Stackadresse
mov ss, ax ; Stacksegment setzen
mov sp, 0 ; Stackpointer auf 0
sti ; Interrupts wieder zulassen
mov si, loadmsg ; Offset von loadmsg nach si
call _putstr ; String ausgeben
call _waitforkey ; auf Tastendruck warten
jmp _reboot ; Rebooten
;************************************************
; FUNKTIONEN / VARIABLEN
;************************************************
; Einen String ausgeben:
_putstr:
lodsb ; Byte von DS:SI nach al laden
or al,al
jz _putstr_ende ; Wenn 0-Byte springe zum Ende
mov ah, 0Eh ; Funktionsnummer nach al
mov bh, 00h ; Bildschirmseite nach bh
mov bl, 07h ; Attribut nach bl
int 10h ; Interrupt 10h aufrufen
jmp _putstr
_putstr_ende:
ret ; Return
; auf Tastendruck warten
_waitforkey:
mov ah, 00h ; Funktionsnummer nach al
int 16h ; Interrupt 16h aufrufen
ret ; Return
; Rebooten (HEX Dump).
_reboot:
db 0EAh
dw 0000h
dw 0FFFFh
loadmsg db "Loading Test-Kernel 0.7 ...",13,10,0
times 512-($-$$)-2 db 0 ; Dateigröße von 512 Bytes erzeugen
dw 0AA55h ; Bootsignatur
ok so viel dazu, den kernel hatte ich ja schon mal gepostet (einfach weiter oben gucken ...)
ich hoffe, dass du mir helfen kannst! also thx!!
falls es dir immer noch zu anstrengend ist, schicke ich dir die dateien auch per e-mail :-) thx...
-
hi
ich hab mal drüber geguckt. was mir aufgefallen ist:
Zum Bootloader:
ist das der komplette Bootloader, mit dem du den Kernel laden willst?
Wenn ja, im Bootloader wird niergendwo ein kernel geladen noch wird zu diesem gesprungen - was deinen oben beschriebenen Programmablauf zum Ergebnis hätte
mfg gurru
-
gurru postete
hi
ich hab mal drüber geguckt. was mir aufgefallen ist:
Zum Bootloader:
ist das der komplette Bootloader, mit dem du den Kernel laden willst?
Wenn ja, im Bootloader wird niergendwo ein kernel geladen noch wird zu diesem gesprungen - was deinen oben beschriebenen Programmablauf zum Ergebnis hätte
mfg gurru
mir scheints auch so. Du musst den Kernel manuell mit Interrupt 0x13 vom bootloader aus in den Speicher laden. Oder hast du ne alte Version deines bootloaders genommen?
-
oh ja verzeiht ... mein fehler!!!
mein bootloader (jetzt wirklich) :-)
;*************************************************
; BOOTLOADER
;*************************************************
org 0h ; Startadresse
jmp 07c0h:_start ; Springe zu _start im Segment 07c0h
;************************************************
; VARIABLEN
;************************************************
loadmsg db "Loading "TEST-Kernel 0.7... ",0
resetmsg db "Reseting bootdrive... ",0
readymsg db "ready",13,10,0
keymsg db "Press any key to start TEST-OS 0.7.",13,10,0
;************************************************
; MAIN
;************************************************
_start:
mov ax, cs ; Segmenregister setzen
mov ds, ax
mov es, ax
; Stack einrichten
cli ; Interrputs verbieten
mov ax, 9000h ; Stackadresse
mov ss, ax ; Stacksegment setzen
mov sp, 0 ; Stackpointer auf 0
sti ; Interrupts wieder zulassen
call _clrscr
call _reset ; Bootlaufwerk resten / Kernel laden
mov si, keymsg ; String ausgeben
call _putstr
mov ax, 1000h
push ax
mov ax, 0h
push ax
retf
; jmp 1000h:0000h ; Springe zum Kernel
;************************************************
; FUNKTIONEN
;************************************************
; Einen String ausgeben:
_putstr:
lodsb ; Byte von ds:si nach al laden
or al,al ; Wenn al= 0 dann wird ZF gesetzt
jz _putstr_ende ; Wenn 0-Byte springe zum Ende
mov ah, 0Eh ; Funktionsnummer nach al
mov bh, 00h ; Bildschirmseite nach bh
mov bl, 07h ; Attribut nach bl
int 10h ; Interrupt 10h aufrufen
jmp _putstr
_putstr_ende:
ret ; Return
; auf Tastendruck warten
_waitforkey:
mov ah, 00h ; Funktionsnummer nach al
int 16h ; Interrupt 16h aufrufen
ret ; Return
; Bildschirm löschen
_clrscr:
mov ah, 0fh
int 10h
mov ah, 00h
int 10h
ret
; Bootlaufwerk reseten
_reset:
mov si, resetmsg
call _putstr
push ds ; ds sichern
mov ah, 00h ; Funktionsnummer nach al
mov dl, 00h ; Bootlaufwerk nach dl (0)
int 13h ; Interrupt 13h aufrufen
pop ds ; ds vom Stapel holen
jc _reset ; bei Fehler, erneuter Versuch
mov si, readymsg
call _putstr
mov ax, 1000h ; Adresse für Kernel von Diskette:
mov es, ax ; es:bx = 1000h:0000h
mov bx, 0
; Kernel von Diskette laden
_loadkernel:
mov si, loadmsg ; Offset von loadmsg nach si
call _putstr ; String ausgeben
mov ah, 2 ; Funktionsnummer nach al
mov al, 5 ; Anzahl der zulesenden Sektoren
mov ch, 0 ; Nummer des Cylinders
mov cl, 2 ; Nummer des Startsektors
mov dx, 0 ; Head, Drive = 0
int 13h ; Interrupt 13h aufrufen
jc _loadkernel ; bei Fehler, erneuter Versuch
mov si, readymsg
call _putstr
ret
times 512-($-$$)-2 db 0 ; Dateigröße von 510 Bytes erzeugen
dw 0AA55h ; + 2 Bytes Bootsignatur --> 512 Bytes
-
hi,
Meiner Meinung nach ist hier schon ein Fehler:
loadmsg db "Loading "TEST-Kernel 0.7... ",0
^------Dieses Anführungszeichen.
Bei anderen Sprachen lösst man das so:
loadmsg db "Loading \"TEST-Kernel 0.7... ",0
aber bei Assembly bin ich mir nicht sicher
mfg
-
Hi,
unter umständen kann es auch an folgenden Dingen liegen:
Du setzt sp auf 0. Beim nächsten push (z.B. bei jedem call) gibt es einen Überlauf in sp. Muss aber nicht sein.
Btw, warum resettest du den fdc controller nochmal? das macht das BIOS schon vorm booten... Brauchst du also garnicht.
MfG GhostCoder
-
also ich habs! der code funktioniert so wie er oben steht. ich habe nur immer unter linux kompiliert (was auf jeden fall keinen unterschied machen sollte) und habe das image auf diskette mit dem Befehl
cat boot.bin kernel.bin > /dev/fd0
erzeugt. das schient nicht 100% sauber zu sein. da es aber immer teilweise funktioniert hat, bin ich nicht davon ausgegangen, dass es daran liegt. unter windows mit rawrite funktionierts. wenn mit trotzdem jemand sagen kann, wie man unter linux das image sauber schreibt, wär das cool :-)! thx für die hilfe
-
Ich bin zwar kein Linux-Freak aber soweit ich weiß kann man mit dem Befehl "dd" Daten direkt in Sektoren kopieren.
"cat" wird eher nur verwendet um Dateien zusammenzufügen. Wäre mir da nicht so sicher das man die Ausgabe dann so ohne weiteres auf fd0 umleiten kann und es dann direkt in den Bootsektor kopiert wird.
-
um TeeJay's gedanken weiterzuführen:
dd if=image of=/dev/fd0
bei mir gings auch mit
cat boot.bin kernel.bin > image;cat image > /dev/fd0