Bootloader: Sprung Sector 1 nach Sector 2
-
Guten Morgen

Ich hab ein Problem, und zwar:
Ich habe momentan einen Bootloader, der nur dafür da ist
um beginnend vom 2. Sektor nach weiteren 5 Sektoren zu schauen,
wenn diese vorhanden sind soll er diese an die Adresse 0x1000:0x0
laden.Soweit, sogut.
Er kommt leider nur nie beim Sektor 2 an, bzw. läd er den eigentlich weiteren Code
nicht.Hoffentlich könnt ihr mir helfen :).
sector1.asm:
org 0h jmp 0x07c0:boot_sec1_main include "video.asm" boot_sec1_main: mov [boot_sec1_drv], dl mov ax, cs mov ds, ax mov es, ax mov ax, 0xb800 mov es, ax ; Load Sector 2 mov si, msg_sec1_read call video_print_message call boot_reset_drv call boot_check_sec2 call boot_read_sec2 mov ax, 0xb800 mov es, ax mov si, msg_sec1_enter call video_print_message ; Jump to Stage 2 mov ax, 0x1000 mov es, ax mov ds, ax jmp 0x1000:0x0 boot_check_sec2: mov ah, 04h mov al, 5 mov ch, 0 mov cl, 2 mov dh, 0 mov dl, [boot_sec1_drv] int 13h mov si, msg_sec1_chk_f jc boot_error boot_reset_drv: mov ah, 0h mov dl, [boot_sec1_drv] int 13h jc boot_reset_drv ret boot_read_sec2: mov ax, 0x1000 mov es, ax ; where to write to es:bx xor cx, cx ; cx = 0 mov bx, cx ; bx = 0 read: mov ah, 02h ; fnc mov al, 5 ; num sectors mov cl, 2 ; sector num mov dh, 0 ; head num mov dl, [boot_sec1_drv] ; drive num int 13h jc read mov si, msg_sec1_fail cmp al, 5 jz ready jne boot_error ready: ret boot_error: cmp si, 0 jz boot_error_ret mov ax, 0xb800 mov es, ax call video_print_message mov ah, 0h int 16h jmp 0xffff:0 boot_error_ret: ret boot_sec1_drv db 0 msg_sec1_chk_f db "Stage 1: Missing Sector 2", 13, 10, "Press Any Key to Reboot", 0 msg_sec1_read db "Stage 1: Reading Sector 2", 13, 10, 0 msg_sec1_enter db "Stage 1: Entering Stage 2", 13, 10, 0 msg_sec1_fail db "Stage 1: Failed Reading Sector 2", 13, 10, "Press Any Key to Reboot", 0 times 510-($-$$) db 0 dw 0x55AAsector2.asm:
org 0h jmp 0x1000:boot_sec2_main include "video.asm" boot_sec2_main: mov ax, 0x1000 mov ds, ax mov es, ax mov ax, 0xb800 mov es, ax ; Resize Stack cli mov ax, 0x9000 mov ss, ax mov sp, 0x0 sti mov al, 2 call video_set_pos_y mov si, msg_sec2_gdt call video_print_message jmp $ msg_sec2_gdt db "Stage 2: Setting up GDT", 13, 10, 0Mit freundlichen Grüßen
-
Hab' ein ret bei
boot_reset_drv vergessen, Fehler ist aber weiterhin noch existent!Hoffe auf lösungen.
-
Da sehe ich potentiell einige Probleme.
Zuerst mal kann ich das zwar wegen der fehlenden video.asm nicht nachprüfen, aber bist du sicher, dass allein dein Bootloader fuer den 1. Sektor noch in 512 Byte passt? Um es mal positiv zu formulieren: Dein Code hat noch deutliche Spielraeume fuer Geschwindigkeits und vor allem Groessenoptimierung.

Von den ganzen kleinen Sachen, wie unnoetiges (einzelnes) Setzen von Registern, unguenstige Konstruktion von Spruengen etc. mal abgesehen, faellt da vor allem die Funktion "boot_check_sec2" auf.
Die Funktion 04h von int 13h ist dazu gut, Daten auf dem Laufwerk mit Daten, die bereits im Speicher liegen zu vergleichen. Mal davon ab, dass du den dazu noetigen Puffer erst gar nicht an die Funktion uebergibst, waere das hier auch eher unnuetz und wird so auch mit an Sicherheit grenzender Wahrscheinlichkeit fehlschlagen.Ob es so sinnvoll ist, read bei Fehlschlag ohne Meldung einfach immer wieder aufzurufen, ist auch fraglich.
Zudem Solltest du schon im Bootsektor als allererstes den Stack initialisieren.
Dazu reicht uebrigens ein; ... ax irgendwie setzen, zB. mov ax, cs mov ss, ax mov sp, 0Auch wenn es in vielen Tutorials anders steht: cli/sti sind hier ueberfluessig(!), da mov ss, m/r16 automatisch die Interrupts fuer die Ausfuehrung des naechsten Befehls ausschliesst.
bootloader schrieb:
Hab' ein ret bei
boot_reset_drv vergessen,[...]Kann ich nicht erkennen...
Das war dann auch erstmal alles, was mir so beim Durchlesen aufgefallen ist.
Wenn es nach den Verbesserungen immer noch Probleme gibt, poste mal den ganzen Code.Uebrigens: Bochs ist ein PC-Emulator mit Debugger. Eignet sich in solchen Faellen evtl. auch zur Fehlersuche.
-
Nobuo T schrieb:
Zuerst mal kann ich das zwar wegen der fehlenden video.asm nicht nachprüfen, aber bist du sicher, dass allein dein Bootloader fuer den 1. Sektor noch in 512 Byte passt? Um es mal positiv zu formulieren: Dein Code hat noch deutliche Spielraeume fuer Geschwindigkeits und vor allem Groessenoptimierung.

Jop, ist zwar nicht mehr soviel Spielraum, aber zum laden von einem weiteren
Sektor gehts noch *g*.Und zur Optimierung: ja, da gibts mit sicherheit ne menge, was man optimieren könnte, bin auch ziehmlich neu auf dem Gebiet

Nobuo T schrieb:
Von den ganzen kleinen Sachen, wie unnoetiges (einzelnes) Setzen von Registern, unguenstige Konstruktion von Spruengen etc. mal abgesehen, faellt da vor allem die Funktion "boot_check_sec2" auf.
Die Funktion 04h von int 13h ist dazu gut, Daten auf dem Laufwerk mit Daten, die bereits im Speicher liegen zu vergleichen. Mal davon ab, dass du den dazu noetigen Puffer erst gar nicht an die Funktion uebergibst, waere das hier auch eher unnuetz und wird so auch mit an Sicherheit grenzender Wahrscheinlichkeit fehlschlagen.Ups. *g*
Hab dann wohl was falsch gelesen.
Ich bin davon ausgegangen, das nach weiteren Sektoren gesucht wird
Nobuo T schrieb:
Ob es so sinnvoll ist, read bei Fehlschlag ohne Meldung einfach immer wieder aufzurufen, ist auch fraglich.
Ich hab gelesen, dass das normal ist ( oder öfters mal passiert ) das er
fehlschlägt, und man einfach solange machen soll bis der Carry-flag nicht mehr
gesetzt ist.Nobuo T schrieb:
Zudem Solltest du schon im Bootsektor als allererstes den Stack initialisieren.
Dazu reicht uebrigens ein; ... ax irgendwie setzen, zB. mov ax, cs mov ss, ax mov sp, 0Auch wenn es in vielen Tutorials anders steht: cli/sti sind hier ueberfluessig(!), da mov ss, m/r16 automatisch die Interrupts fuer die Ausfuehrung des naechsten Befehls ausschliesst.
Ja, klingt leicht logisch

Und danke für den Tipp wegen cli/sti.Nobuo T schrieb:
bootloader schrieb:
Hab' ein ret bei
boot_reset_drv vergessen,[...]Kann ich nicht erkennen...
Ist ja auch nicht so wichtig, solange der Code rennt *g*.
Nobuo T schrieb:
Das war dann auch erstmal alles, was mir so beim Durchlesen aufgefallen ist.
Wenn es nach den Verbesserungen immer noch Probleme gibt, poste mal den ganzen Code.Danke dir

Nobuo T schrieb:
Uebrigens: Bochs ist ein PC-Emulator mit Debugger. Eignet sich in solchen Faellen evtl. auch zur Fehlersuche.
[/quote]
Ich weiß nicht ob ich ein sonderfall bin, aber ich bekomm Bochs einfach nicht zum laufen. Vielleicht bin ich auch nur zu faul zum einrichten *g*.
-
bootloader schrieb:
Nobuo T schrieb:
Ob es so sinnvoll ist, read bei Fehlschlag ohne Meldung einfach immer wieder aufzurufen, ist auch fraglich.
Ich hab gelesen, dass das normal ist ( oder öfters mal passiert ) das er
fehlschlägt, und man einfach solange machen soll bis der Carry-flag nicht mehr
gesetzt ist.Ja, ist moeglich, dass das erstmal fehlschlaegt. Dann sollte man es nochmal versuchen, aber 1. sollte dann vor dem naechsten Leseversuch erstmal ein reset (int 13h, Funktion 0) gemacht werden und 2. kann es auch sehr gut vorkommen, dass die Diskette im Eimer ist und das Lesen immer fehlschlaegt.
Dann waere es sinnvoll, nach vielleicht 8 Versuchen abzubrechen und eine Fehlermeldung anzuzeigen.bootloader schrieb:
Nobuo T schrieb:
Uebrigens: Bochs ist ein PC-Emulator mit Debugger. Eignet sich in solchen Faellen evtl. auch zur Fehlersuche.
Ich weiß nicht ob ich ein sonderfall bin, aber ich bekomm Bochs einfach nicht zum laufen. Vielleicht bin ich auch nur zu faul zum einrichten *g*.
Ja, ist einiges an Arbeit - auch bis man mit dem Debugger zurechtkommt (zumindest bei der letzten, ~2 Jahre alten Version, die ich ausprobiert habe, war das sehr umstaendlich), spart aber zumindest auf jeden Fall Zeit und Disketten, sobald es laeuft.

-
Nobuo T schrieb:
bootloader schrieb:
Nobuo T schrieb:
Ob es so sinnvoll ist, read bei Fehlschlag ohne Meldung einfach immer wieder aufzurufen, ist auch fraglich.
Ich hab gelesen, dass das normal ist ( oder öfters mal passiert ) das er
fehlschlägt, und man einfach solange machen soll bis der Carry-flag nicht mehr
gesetzt ist.Ja, ist moeglich, dass das erstmal fehlschlaegt. Dann sollte man es nochmal versuchen, aber 1. sollte dann vor dem naechsten Leseversuch erstmal ein reset (int 13h, Funktion 0) gemacht werden und 2. kann es auch sehr gut vorkommen, dass die Diskette im Eimer ist und das Lesen immer fehlschlaegt.
Dann waere es sinnvoll, nach vielleicht 8 Versuchen abzubrechen und eine Fehlermeldung anzuzeigen.Stimmt auch mal wieder; wenn man so vertieft in seinem Code ist,
kommt man da auch nicht drauf
Nobuo T schrieb:
bootloader schrieb:
Nobuo T schrieb:
Uebrigens: Bochs ist ein PC-Emulator mit Debugger. Eignet sich in solchen Faellen evtl. auch zur Fehlersuche.
Ich weiß nicht ob ich ein sonderfall bin, aber ich bekomm Bochs einfach nicht zum laufen. Vielleicht bin ich auch nur zu faul zum einrichten *g*.
Ja, ist einiges an Arbeit - auch bis man mit dem Debugger zurechtkommt (zumindest bei der letzten, ~2 Jahre alten Version, die ich ausprobiert habe, war das sehr umstaendlich), spart aber zumindest auf jeden Fall Zeit und Disketten, sobald es laeuft.

Mh. Ich benutze momentan 'Sun xVM VirtualBox'.
Läuft eigentlich super, aber manchmal versuch ich die Schuld einfach
auf den Emulator zu schiebem :D.
-
Mh.
Also springen mag er wohl immernoch nicht wirklich,
oder könnte es sein, das ich beim 2. Sektor Code irgendetwas falsch mache ( auch wenn ich jetzt nichts falsches erkenne )?Hier nochmal alles, was ich momentan benutze:
video.asm:
; CODE SEGMENT ; Video print Routine video_print_message_do: call video_print_char video_print_message: lodsb ; load byte cmp al, 0 ; check byte jnz video_print_message_do ; print byte if not zero ret video_print_char: cmp al, 13 ; check if a newline is wanted je video_newline ; set y position cmp al, 10 ; check if a rewind is wanted je video_rewind ; set x position jne video_print_char_r ; print byte ret ; return video_print_char_r: mov ah, [video_color] ; attribute: white on black mov cx, ax ; save movzx ax, byte [video_pos_y]; set ah to 0h and copy the y pos to al mov dx, 160 ; 2 bytes. first byte is the char, second the color mul dx movzx bx, byte [video_pos_x]; same as 5 lines above shl bx, 1 ; skip attribute mov di, 0 ; set memory add di, ax ; set position to write to add di, bx ; set position to write to mov ax, cx ; reget char with color stosw ; and write add byte [video_pos_x], 1 ; inc x position ret ; go back video_newline: add byte [video_pos_y], 1 ret video_rewind: mov byte [video_pos_x], 0 ret video_set_pos_x: cmp al, 0 jle video_set_pos_x_end mov byte [video_pos_x], al video_set_pos_x_end: ret video_set_pos_y: cmp al, 0 jle video_set_pos_y_end mov byte [video_pos_y], al video_set_pos_y_end: ret video_set_color: cmp ah, 0 je video_set_color_end mov [video_color], ah video_set_color_end: ret ; DATA SEGMENT video_color db 0x0F video_pos_x db 0 video_pos_y db 0sektor1.asm:
org 0h jmp 0x07c0:boot_sec1_main include "video.asm" boot_sec1_main: ; Init Stack mov ax, 0x9000 mov ss, ax mov sp, 0 mov [boot_sec1_drv], dl ; Save drive num ; Init Data Segment mov ax, cs mov ds, ax ; Load Sector 2 mov ax, 0xb800 mov es, ax mov si, msg_sec1_read call video_print_message call boot_read_sec2 ; Jump to Stage 2 mov ax, 0xb800 mov es, ax mov si, msg_sec1_enter call video_print_message jmp 0x1000:0x0 boot_reset_drv: mov ah, 0h mov dl, [boot_sec1_drv] int 13h jc boot_reset_drv ret boot_read_sec2: mov ax, 0x1000 mov es, ax ; where to write to es:bx xor cx, cx ; cx = 0 mov bx, cx ; bx = 0 read: mov ah, byte [msg_sec1_read_m] mov al, byte [msg_sec1_count] cmp al, ah ; try to read 8 times, else the sector isnt present or the disk is mov al, 0 ; corrupt je chk call boot_reset_drv mov ah, 02h ; fnc mov al, 5 ; num sectors mov cl, 2 ; sector num mov dh, 0 ; head num mov dl, [boot_sec1_drv] ; drive num int 13h ; increment read num add [msg_sec1_count], 1 jc read ; check if all went fine or if ; a disk is corrupt or a sector is missing chk: mov si, msg_sec1_fail cmp al, 5 jne boot_error ret boot_error: ; error string set? cmp si, 0 jz boot_error_ret ; print error string mov ax, 0xb800 mov es, ax call video_print_message ; Print Message mov ah, 0h int 16h ; Wait for a Key jmp 0xffff:0 ; Reboot ; no string set boot_error_ret: ret boot_sec1_drv db 0 ; drive to read from msg_sec1_count db 0 ; sector read runs msg_sec1_read_m db 8 ; max amount of runs msg_sec1_read db "Stage 1: Reading Sector 2", 13, 10, 0 msg_sec1_chk_f db "Stage 1: Missing Stage 2", 13, 10, "Press Any Key to Reboot", 0 msg_sec1_enter db "Stage 1: Entering Stage 2", 13, 10, 0 msg_sec1_fail db "Stage 1: Failed Reading Sector 2 (Missing/Corrupt Disk?)", 13, 10, "Press Any Key to Reboot", 0 times 510-($-$$) db 0 dw 0x55AAsektor2.asm:
org 0h jmp 1000h:boot_sec2_main include "video.asm" boot_sec2_main: mov ax, cs mov ds, ax mov es, ax mov ax, 0xb800 mov es, ax mov al, 2 call video_set_pos_y mov si, msg_sec2_gdt call video_print_message jmp $ msg_sec2_gdt db "Stage 2: Setting up GDT", 13, 10, 0
-
mov dl, [boot_sec1_drv] ; drive num int 13h ; increment read num add [msg_sec1_count], 1 jc readDas geht so nicht, da add die Flags veraendert - hier vor allem das CF auf 0 setzen wird. Sonst habe ich erstmal eigentlich nichts weiter gefunden. Habe gerade auch kein Bochs zur Hand...

-
add setzt doch nur das Zero-flag?
Ich meine, dass adc das Carry-flag benutzt?!
//EDIT:
Hab mir Bochs mal angeschaut, aber irgendwie mag er die größe der Datei für Floppy net ganz *grübel*
-
Hol dir mal eine Brauchbare Befehlsreferenz.
add setzt folgende Flags: o,s,z,a,p,c
adc addiert das c-flag (also 0 oder 1) mit dem 2. zum 1. Operanden und setzt es danach wie add entsprechend neu.
inc dagegen aendert das c-flag nicht.
-
Ok.
Das Problem wurde entlüftet: Die Emus streiken bei Verwendung einer kleineren Floppy Datei ( z.B. +/-800 Bytes ).Einfach ein leere Datei mit festen größen ( Floppymäßig: 1.44MB z.B. )
und dann den assemblierten Code einfach einfügen.