Ich habe mir die OS-Seite von Erhard Henkes angeshen...
-
und bin positiv überrascht.
Ich teste das Betriebssystem unter Virtual PC und habe mir eine vfd (Virtual Disk)-Datei erstellt. Dann habe ich die boot.bin und die kernel.bin in die Datei myos.img anhand des Cmd-Befehls "copy" kopiert. Die Datei myos.img habe ich dann per RawDisk auf die virtuelle Diskette geschrieben.
Als ich das Betriebssystem dann testen wollte, hing sich der Computer stets auf... Selbst der Bootloader wurde nicht geladen.
Woran könnte das liegen? Bei den Tutorials davor - als noch Bootloader und Kernel in einer asm-Datei lagen - hatte ich keine Probleme. Da lief noch das Betriebssystem.
-
Kommt denn irgendeine (Fehler-)Meldung?
Ansonsten würde ich es einfach mal in der von ehenkes geschilderten Art und Weise versuchen (also keine vfd-Datei), und diese in VPC laden.
-
Eine Fehlermeldung erscheint nicht. Das Betriebssystem hängt sich lediglich dabei auf und es erscheint überhaupt keine Meldung. Wie meinst du das ohne vfd-Datei? Ein Diskettenlaufwerk habe ich jetzt nicht.
-
Zeig mal deinen Code und beschreib genau wie du das zusammenkopierst. Vielleicht ist da irgendwo ein kleiner Fehler.
-
;boot.asm org 0x7C00 ; set up start address ; setup a stack mov ax, 0x9000 ; address of the stack SS:SP mov ss, ax ; SS = 0x9000 (stack segment) xor sp, sp ; SP = 0x0000 (stack pointer) ; start mov [bootdrive], dl ; boot drive from DL call load_kernel ; load kernel ; jump to kernel jmp 0x1000:0x0000 ; address of kernel bootdrive db 0 ; boot drive loadmsg db "bootloader message: loading kernel ...",13,10,0 ; print string print_string: lodsb ; grab a byte from SI or al, al ; NUL? jz .done ; if the result is zero, get out mov ah, 0x0E int 0x10 ; otherwise, print out the character! jmp print_string .done: ret ; read kernel from floppy disk load_kernel: mov dl,[bootdrive] ; select boot drive xor ax, ax ; mov ax, 0 => function "reset" int 0x13 jc load_kernel ; trouble? try again load_kernel1: mov ax, 0x1000 mov es, ax ; ES:BX = 0x10000 xor bx, bx ; mov bx, 0 ; set parameters for reading function ; 8-Bit-wise for better overview mov dl,[bootdrive] ; select boot drive mov al,10 ; read 10 sectors mov ch, 0 ; cylinder = 0 mov cl, 2 ; sector = 2 mov dh, 0 ; head = 0 mov ah, 2 ; function "read" int 0x13 jc load_kernel1 ; trouble? try again ; show loading message mov si,loadmsg call print_string ret times 510-($-$$) hlt db 0x55 db 0xAA
;kernel.asm mov ax, 0x1000 ; set up segments mov ds, ax mov es, ax mov si, welcome call print_string loop: mov si, prompt call print_string mov di, buffer call get_string mov si, buffer cmp byte [si], 0 ; blank line? je loop ; yes, ignore it mov di, cmd_hi ; "hi" command call strcmp jz .helloworld mov si, buffer mov di, cmd_help ; "help" command call strcmp jz .help mov si, buffer mov di, cmd_questionmark ; "?" command call strcmp jz .help mov si, buffer mov di, cmd_exit ; "exit" command call strcmp jz .exit mov si,badcommand call print_string jmp loop .helloworld: mov si, msg_helloworld call print_string jmp loop .help: mov si, msg_help call print_string jmp loop .exit: mov si, msg_exit call print_string jmp 0xffff:0x0000 ; Reboot welcome db 'HenkesSoft 0.01 (version from Mar 14, 2009)', 13, 10, 0 msg_helloworld db 'Hello World!', 13, 10, 0 badcommand db 'Command unknown.', 13, 10, 0 prompt db '>', 0 cmd_hi db 'hi', 0 cmd_help db 'help', 0 cmd_questionmark db '?', 0 cmd_exit db 'exit', 0 msg_help db 'Commands: hi, help, ?, exit', 13, 10, 0 msg_exit db 'Reboot starts now.', 13, 10, 0 buffer times 32 db 0 ; ================ ; calls start here ; ================ print_string: lodsb ; grab a byte from SI or al, al ; logical or AL by itself jz .done ; if the result is zero, get out mov ah, 0x0E int 0x10 ; otherwise, print out the character! jmp print_string .done: ret get_string: xor cl, cl .loop: xor ah, ah ; mov ah, 0 int 0x16 ; wait for keypress cmp al, 8 ; backspace pressed? je .backspace ; yes, handle it cmp al, 13 ; enter pressed? je .done ; yes, we're done cmp cl, 31 ; 31 chars inputted? je .loop ; yes, only let in backspace and enter mov ah, 0x0E int 0x10 ; print out character stosb ; put character in buffer inc cl jmp .loop .backspace: or cl, cl ; zero? (start of the string) jz .loop ; if yes, ignore the key dec di mov byte [di], 0 ; delete character dec cl ; decrement counter as well mov ax, 0x0E08 int 0x10 ; backspace on the screen mov al, ' ' int 0x10 ; blank character out mov al, 8 int 0x10 ; backspace again jmp .loop ; go to the main loop .done: mov al, 0 ; null terminator stosb mov ax, 0x0E0D int 0x10 mov al, 0x0A int 0x10 ; newline ret strcmp: .loop: mov al, [si] ; fetch a byte from SI cmp al, [di] ; are SI and DI equal? jne .done ; if no, we're done. or al, al ; zero? jz .done ; if yes, we're done. inc di ; increment DI inc si ; increment SI jmp .loop ; goto .loop .done: stc ret
-
florida schrieb:
Eine Fehlermeldung erscheint nicht. Das Betriebssystem hängt sich lediglich dabei auf und es erscheint überhaupt keine Meldung. Wie meinst du das ohne vfd-Datei? Ein Diskettenlaufwerk habe ich jetzt nicht.
Ich weiß nicht, wie ehenkes das macht, aber ich nehme an, er hat irgendwo mal ein Diskettenabbild erstellt (roh, kein vfd).
-
http://www.henkessoft.de/OS_Dev/OS_Dev1.htm#mozTocId427538
nasm boot.asm -f bin -o boot.bin nasm kernel.asm -f bin -o kernel.bin cmd /c copy /b boot.bin + kernel.bin MyOS.bin partcopy MyOS.bin 0 400 -f0
- Schau dir MyOS.bin mit dem Hex-Editor an, ob alles dabei ist.
- Achte darauf, dass die Daten nach dem Kopieren wirklich im Bootsektor anfangen (da liegt offensichtlich dein Fehler)
Probiere es mal mit http://www.chrysocome.net/dd anstelle rawwrite (Das verwende ich nicht mehr)
So kopiere ich z.B. das aktuelle Image auf eine Floppy zum Booten:
dd if=FloppyImage.img of=\\.\A:
Vielleicht kann man das auf die virtuelle Floppy übertragen.
Ansonsten verwende qemu:
qemu.exe -fda MyOS.bin
... oder bochs: (Bochs config-Datei)
floppya: 1_44=MyOS.bin, status=inserted
oder
floppya: 1_44=G:\OSDev\Test\MyOS.bin, status=inserted
Umkopieren ist auf jeden Fall falsch. Dieses Binärformat ist bereits Rohformat, also die binären Daten, Byte für Byte, wie sie auf den ersten beiden Sektoren (jeweils 512 == 0x200 Byte) auftauchen sollen.
Geübter Umgang mit den Tools ist bei OSDev wichtig. Probiere also bitte die ganze Kiste durch. Es gibt auch noch VBox und VMWare Player.
-
Bei Qemu kommt jetzt "Lade Kernel..." und dann hängt sich gleich das OS auf.
... Hab den Fehler gefunden ...
;kernel.asm times 510-($-$$) hlt ; as alternative to db 0
-
Könnte man den Kernel anstatt mit C vielleicht auch in Pascal schreiben?
-
Ja, kann man. Du kannst das hier als Ansatz dafür nehmen. Alles weitere läuft so ähnlich wie in C, nur eben mit anderer Syntax. Die Pascal-Runtime steht dir erstmal nicht zur Verfügung - wenn der Compiler meckert, dass er irgendeine Funktion aus der Runtime brauch, aber nicht findet, dann musst du in der system.pas die entsprechenden Funktionen implementieren.
-
Könnte man den Kernel anstatt mit C vielleicht auch in Pascal schreiben?
C wurde extra für die Erstellung von Betriebssystemen geschaffen, soweit ich weiß. Pascal ist sicher auch möglich, aber man sondert sich damit ab, genau wie mit D. Dann würde ich eher C++ anpeilen.
-
Pascal und C nimmt sich nicht viel. Da bist du unter Umständen mit C++ von den Konzepten her weiter weg. Was natürlich wahr ist, ist, dass so gut wie alle Beispiele in C geschrieben sind. Lesen sollte man es also schon können.
-
taljeth schrieb:
Pascal und C nimmt sich nicht viel. Da bist du unter Umständen mit C++ von den Konzepten her weiter weg. Was natürlich wahr ist, ist, dass so gut wie alle Beispiele in C geschrieben sind. Lesen sollte man es also schon können.
Wer C++ kann, kann C lesen. Also wäre C++ keine schlechte Basis für einen OS-Entwickler. Wobei ich selbst sagen muss, dass ich einige Kniffe in C erst durch die Anwendung in PrettyOS gelernt habe, obwohl ich vorher schon halbwegs gut C++ konnte.
-
Ist die Menge derjenigen, die C++ wirklich beherrschen nicht so überschaubar, dass die Aussage irrelevant ist?
Ich habe schon genug Leute gesehen, die von sich behauptet haben, C++ zu können und dann an den C-Beispielen grandios gescheitert sind. Die ideale Programmiersprache für OS-Dev ist diejenige, die man in- und auswendig kennt. Wenn du mit Nebensächlichkeiten wie der Sprache oder dem Compiler kämpfen musst, wird ein sowieso schon schwieriges Projekt wie ein OS nochmal deutlich schwieriger. (Andererseits darf man das auch nicht zu sehr überbewerten: tyndur war mein erstes ernsthaftes Projekt in C)
-
Wichtig ist, dass man am Ball und neugierig bleibt. Entweder hat man diese innere Kraft oder man hat sie nicht. Hat man sie, geht es immer weiter, und es wird nicht wirklich langweilig.
-
Erhard ich glaube ich habe einen Fehler in deinem Tutorial entdeckt:D:-P.
Bei Seite 1 wo es um die outportb und set_cursor Funktion geht, steht, man würde an die Ports 0x0E und 0x0F Befehle senden, aber das stimmt doch gar nicht. Man sendet doch bei VGA an den Port 0x3D4 den Befehl 0x0E um dann an 0x3D5 das High Byte zu senden und dann 0x0F an 0x3D4 um dan an 0x3D5 das Low byte zu senden oder nicht? Zudem sind glaube ich auch bei der Funktion outportb die Parameter port und value vertauscht. müsste port nicht value sein und value port ? Oder ich verstehe das gerade komplett falsch?
Eine frage habe ich auch noch, was genau passiert durch den rechtsschift um 8 und dann dem UND mit 0xFF beim High byte und dem UND mit 0xFF bei dem Low Byte?Lg freeG
-
kannst du bitte den code genau darstellen? IST und das, was du für richtig hältst.
-
Erhard Henkes schrieb:
kannst du bitte den code genau darstellen? IST und das, was du für richtig hältst.
Sorry, mein Fehler, hatte ganz vergessen, dass ja AT&T Syntax verwendet wird, bzw dass dort eben die Operanden im Vergleich zur Intel Syntax vertauscht sind. Von daher stimmt alles;-), hier trotzdem mal der Code den ich meinte. Aber wie gesagt, passt alles
inline void outportb(unsigned int port,unsigned char value) { asm volatile ("outb %%al,%%dx"::"d" (port), "a" (value)); }; void update_cursor(int row, int col) { unsigned short position = (row*80) + col; // cursor HIGH port to vga INDEX register outportb(0x3D4, 0x0E); outportb(0x3D5, (unsigned char)((position>>8)&0xFF)); // cursor LOW port to vga INDEX register outportb(0x3D4, 0x0F); outportb(0x3D5, (unsigned char)(position&0xFF)); };
Lg freeG
-
Sorry, mein Fehler, hatte ganz vergessen, dass ja AT&T Syntax verwendet wird
Na, dann ist doch alles bestens.
-
Jap, allerdings ist mir was anderes aufgefallen. Man muss doch als Limit der GDT fürs GDT-Register die Größe der GDT in Bytes-1 angeben. In deinem Tutorial wird allerdings einfach nur 24 Byte,also 3 Einträge verwendet und nicht 23 Byte. Wieso hast du das minus 1 weggelassen?
Lg freeG