Zweiten sector von USB stick lesen



  • Hi,
    Ich bin mit meinem bootloader jetzt bei der BIOS Funktion 13h ah=0x02 angekommen (Sektoren in den Speicher lesen).
    Die parameter der Funktion übergebe ich in den Registern wie hier beschrieben:
    http://www.ctyme.com/intr/rb-0607.htm
    Ich bekomme immer den status code 1 zurück (invalid function in AH or invalid parameter). Ich bin mir aber fast zu 100% sicher das die parameter wie ich sie übergeben habe so richtig sind:
    http://www.ctyme.com/intr/rb-0606.htm#Table234

    Hier ist der bootloader:

    [ORG 0x7c00]                    ; The bootsector program will start at 0x7c00 and end at 0x7e00 (512bytes)
                                    ; The drive number this program is booted from is stored in dl
       MOV   BYTE[DriveNumber], dl  ; Save the drive number to memory
       XOR   ax, ax                 ; Set ax to zero
       MOV   es, ax                 ; Set the extra segment to address 0x0000
       MOV   ds, ax                 ; Set the data segment to address 0x0000
       MOV   ss, ax                 ; Set the stack segment to address 0x0000
       MOV   bp, 0x8000             ; Set the stack base pointer shortly after the end of the bootsector program
       MOV   sp, bp                 ; The stack will grow in negative direction
       JMP   begin
    
    TestString   db "Hello Computer", 0
    TestString2  db "Expect Me", 0
    NumberBuffer db "------", 0
    HexString    db "0123456789ABCDEF", 0
    InfoMessage  db "Could not read sector(s):", 0
    InfoMessage2 db "Drive Number:", 0
    DriveNumber  db 0x00
    LetterZero   db '0'
    
    begin:
       ;MOV ah, 0x02
       ;INT 0x10
    
       MOV  cx, 0x0202
       MOV  dx, TestString2
       CALL printString
    
       MOV  cx, 0x0000
       MOV  dx, TestString
       CALL printString
    
       MOV  cx, 0x0004
       MOV  dx, InfoMessage2
       CALL printString
    
       MOV  cx, 0x0E04
       MOV  dx, 0x0000
       MOV  dl, BYTE[DriveNumber]
       CALL printValue
    
       CALL readSecondSector
    
    hang:
       jmp hang
    
    ; -------------------------------------------------------------
    ; 0x0 = black         0x1 = blue
    ; 0x2 = green         0x3 = cyan
    ; 0x4 = red           0x5 = magenta
    ; 0x6 = brown         0x7 = white
    ; 0x8 = grey          0x9 = bright blue
    ; 0xA = bright green  0xB = bright cyan
    ; 0xC = bright red    0xD = bright magenta
    ; 0xE = bright yellow 0xF = bright white
    ;
    ; In text video memory mode the screen resolution will be
    ; 80 columns x 25 lines.
    ; This function will print a single letter to text video memory
    ;
    ; 1.Parameter cx = position (low=y heigh=x)
    ; 2.Parameter dx = letter (low=letter heigh=attribute)
    printLetter:
       PUSHA               ; Save the state of all registers to the stack
       MOV   ax, WORD 0    ; Set ax to zero
       MOV   al, 160       ; 80 columns = 160 bytes (2bytes per letter)
       MUL   cl            ; Multiply y position with the number of columns
       MOVZX bx, ch        ; Save the x position in the full bx register
       SHL   bx, 1         ; Multiply the x position with two because every letter uses 16bit
    
       MOV di, 0           ; Go to the begin of video memory
       ADD di, bx          ; Add x offset
       ADD di, ax          ; Add y offset
       MOV bx, 0xb800      ; Set bx to the text video memory address
       MOV es, bx          ; Set the extra segment to the text video memory address
       MOV WORD[es:di], dx ; write letter to video memory
       POPA                ; Restore the state of all registers
       RET                 ; Return
    
    ; -------------------------------------------------------------
    ; Print a string to text video memory
    ; cx = position to print to (low=y heigh=x)
    ; dx = string pointer (low=letter heigh=attribute)
    printString:
       PUSHA                ; Save the state of all registers to the stack
       MOV ax, WORD 0       ; Use ax as a counter variable
    .printLoopBegin:
       PUSH dx              ; Save the address of the string to the stack
       MOV  bx, dx          ; Save address of the string to be printed in bx
       ADD  bx, ax          ; Add the counter value to the string address
       MOV  dl, BYTE[bx]    ; Save the current letter to dl
       MOV  dh, 0x1F        ; Set the color attribute of the current letter to dh
    
       CMP dl, BYTE 0       ; Compare the current letter with zero
       JE .printLoopEnd     ; If the current letter is zero then
                            ; jump to the end of the printing loop
       CALL printLetter     ; Print the current letter to the screen
       INC  ch              ; Increment the x position
       INC  ax              ; Increment the counter
       POP  dx              ; Retrieve the address of the string
       JMP  .printLoopBegin ; Jump to the begin of the loop
    .printLoopEnd:
       POP  dx              ; Pop dx from the stack because after jumping out of the loop, dx will still be on the stack
       POPA                 ; Restore all registers
       RET                  ; Return
    
    ; -------------------------------------------------------------
    ; Print a number to the screen in 'text video memory' mode
    ; cx = position (low=y heigh=x)
    ; dx = value
    printValue:
       PUSHA                          ; Save all registers to the stack
       PUSH cx                        ; Save position to print to
       MOV  ax, dx                    ; Save the value to be printed to ax
       MOV  cx, WORD 0                ; Use cx as a counter
    .clearLoopBegin:                  ; This loop will fill the number buffer with '0' letters
       MOV dl      , BYTE[LetterZero] ; Save the letter '0' to dl
       MOV bx      , NumberBuffer     ; Set bx to the address of the buffer where the number is printed to
       ADD bx      , cx               ; Add the counter value to the number buffers address
       MOV BYTE[bx], dl               ; Write the letter in dl to the number buffer
       INC cx                         ; Increment the counter
       CMP cx      , WORD 6           ; Test if the counter is at value 6
       JE  .clearLoopEnd              ; If the counter is 6 jump out of the loop
       JMP .clearLoopBegin            ; Jump to the begin of the loop
    .clearLoopEnd:
       MOV cx, WORD 0                 ; Set the counter to zero again
    .divLoopBegin:                    ; THis loop will divide the value in ax in every round by 10
       MOV dx, WORD 0                 ; The remainder of the div operation will be stored in dx
       MOV bx, WORD 10                ; Set bx to 10
       DIV bx                         ; Divide ax by bx (10)
    
       MOV bx, HexString              ; Save the address of the number string to bx
       ADD bx, dx                     ; Add the remainder to the address of the number string
       MOV dl, BYTE[bx]               ; Save the letter to dl
    
       MOV bx      , NumberBuffer     ; Set bx to the address of the buffer where the number is printed to
       ADD bx      , WORD 5           ; Set the address to the last element of the buffer
       SUB bx      , cx               ; Substract the counter value from the buffer address
       MOV BYTE[bx], dl               ; Write the letter to the buffer
       INC cx                         ; Increment the counter
    
       CMP ax, WORD 0                 ; Thest if the value that should be printed is zero
       JE  .divLoopEnd                ; If the value is zero then jump out of the loop
       JMP .divLoopBegin              ; Jump to the begin of the dividing loop
    .divLoopEnd:
       POP  cx                        ; Restore the printing position from the stack to cx
       MOV  dx, NumberBuffer          ; Set dx to the address of the number buffer
       CALL printString               ; Print the number buffer to the screen
       POPA                           ; Restore all registers
       RET                            ; Return
    
    ; ------------------------------------------------------------------ ;
    readSecondSector:
       MOV dl, [DriveNumber]          ; Select the drive to read from
       MOV ch, 0                      ; Select cylinder 0
       MOV dh, 0                      ; Select head 0
       MOV al, 1                      ; Set the number of sectors to read
       MOV cl, 2                      ; Begin reading from the second sector (the sector immediately after the boot sector)
    
       MOV bx, 0                      ; Set bx to zero
       MOV es, bx                     ; Set the extra segment to zero
       MOV bx, 0x9000                 ; The data to be read will be stored at [es:bx] (address 0x0000:0x9000)
    
       MOV ah, 0x02                   ; Set the BIOS interrupt function to "read sector function"
       INT 0x13                       ; Call the interrupt
       JC  .DiskReadFailed            ; Jump if the carry flag is set
    
       MOV   cx, 0x1A06               ; Print at line 6 after the info message
       MOVZX dx, ah                   ; Store the status code of interrupt 0x13 into dx
       CALL  printValue               ; Print the status code of interrupt 0x13
    
       MOV  cx, 0x0008                ; Set the printing position to line 8
       MOV  dx, 0x9000                ; Set the address where the second sector is loaded to memory to dx
       CALL printString               ; Print the string from the second sector to the screen
       RET
    .DiskReadFailed:
       MOV   cx, 0x0006               ; Print at line 6
       MOV   dx, InfoMessage          ; Store the address of an info message into dx
       CALL  printString              ; Print the info message
       MOV   cx, 0x1A06               ; Print at line 6 after the info message
       MOVZX dx, ah                   ; Store the status code of interrupt 0x13 into dx
       CALL  printValue               ; Print the status code of interrupt 0x13
       RET
    
    ; ------------------------------------------------------------------ ;
    
    TIMES 510-($-$$) DB 0  ; Fill the file til byte 510 with zeros
    DB 0x55                ; Set byte 511 to the magic bootsector number
    DB 0xAA                ; Set byte 512 to the magic bootsector number
    
    ; ------------------------------------------------------------------ ;
    
    DB "This text is stored on an USB flash drive this bootloader was started from", 0
    TIMES 1024-($-$$) db 0x00
    

    Die Funktion die den zweiten Sektor lesen soll heist hier "readSecondSector"
    Kann es sein das ich für USB flash drives eine andere Funktion verwenden muss? Ich lese immer nur etwas von HDDs und Floppies. Ein usb stick hat auch nicht wirklich leseköpfe 😉

    MfG
    Silvio



  • Ich habe rausgefunden, dass ich wohl tatsächlich nicht int 13h ah=0x02 verwenden kann um den zweiten sector zu lesen.
    Da gibt es wohl eine Erweiterung zu int 13h (int 13h extensions) womit es funktionieren soll.
    Ich habe eine kleine Funktion geschrieben, die testet ob int 13h extensions verfügbar sind:

    ExtensionInfoMessage   db "Interrupt 13h extensions available", 0
    NoExtensionInfoMessage db "No interrupt 13h extensions available", 0
    
    ; ------------------------------------------------------------------ ;
    checkInt13Extensions:
       MOV bx, 0xAA55                   ; Set bx to the magic number
       MOV ah, 0x41                     ; Select the interrupt 13h function 0x41
       INT 0x13                         ; Call interrupt 13h
       JC  .NoInt13Extension            ; If the interrupt 13h extensions are supported then the carry flag is not set
    
       CMP bx, 0xAA55                   ; Test if the magic number is still present
       JNE .NoInt13Extension            ; Go to error handling if not
    
       MOV   cx, 0x0006                 ; Write info message to line 6
       MOV   dx, ExtensionInfoMessage   ; Set the address of the info message to dx
       CALL  printString                ; print the info message
       RET
    .NoInt13Extension:
       MOV   cx, 0x0006                 ; Write info message to line 6
       MOV   dx, NoExtensionInfoMessage ; Set the address of the info message to dx
       CALL  printString                ; print the info message
       RET
    

    Bei mir sind die Erweiterungen anscheinend nicht verfügbar. Kann mal jemand testen ob bei ihm die Erweiterungen verfügbar sind?

    Für mich stellt sich jetzt natürlich die frage wie ich Daten von dem stick in den Speicher bekomme... 😕

    MfG
    Silvio


Log in to reply