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 0x55AA
    

    sector2.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, 0
    

    Mit 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, 0
    

    Auch 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, 0
    

    Auch 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 0
    

    sektor1.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 0x55AA
    

    sektor2.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 read
    

    Das 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.


Anmelden zum Antworten