3

Trying to read data from disk (from the same file), loading 2 additional 512-byte sectors into memory. Disk read function as is:

; read DH sectors to ES:BX from drive DL
disk_read:
    push dx 

    push bx  ; Tried to check if disk is ready first, this code runs without errors
    mov ah, 0x10
    int 0x13
    jc disk_not_ready
    mov bx , DISK_CURRENT_STATUS_MSG
    call print_string
    mov bx, 0
    mov bl , ah
    call print_hex
    pop bx

    mov ah , 0x42   ; BIOS read sector function
    mov al , dh     ; Read DH sectors
    mov ch , 0x00   ; Select cylinder 0
    mov dh , 0x00   ; Select head 0
    mov cl , 0x02   ; Start reading from second sector (i.e.
                    ; after the boot sector)

    int 0x13        ; BIOS interrupt to read from disk
    jc disk_read_error_general  ; Jump if error (i.e. carry flag set)
    pop dx                      ; Restore DX from the stack
    cmp dh , al                 ; if AL (sectors read) != DH (sectors expected)
    jne disk_read_error_number_of_sectors_read_differs  ; display error message
    cmp dh , al                 ; if AL (sectors read) != DH (sectors expected)
    je disk_read_success        ; display success message

    disk_read_exit:
        ret

disk_read_success:
    mov bx , DISK_READ_SUCCESS_MSG
    call print_string
    jmp disk_read_exit

disk_read_error_general:
    mov bx , DISK_READ_ERROR_GENERAL_FAIL_MSG
    call print_string
    mov bx , DISK_CURRENT_STATUS_MSG
    call print_string
    mov bx, 0
    mov bl , ah
    call print_hex
    jmp $

disk_not_ready:
    mov bx , DISK_NOT_READY_ERROR_MSG
    call print_string
    jmp $

disk_read_error_number_of_sectors_read_differs:
    mov bx , DISK_READ_ERROR_NUMBER_OF_SECTORS_DIFFERS_MSG
    call print_string
    jmp $

; Variables
DISK_READ_SUCCESS_MSG:
    db "Disk read were successful!" , 0

DISK_NOT_READY_ERROR_MSG:
    db "Disk is not ready for reading!" , 0

DISK_READ_ERROR_GENERAL_FAIL_MSG:
    db "Disk read error, carry in CF were not set!" , 0

DISK_READ_ERROR_NUMBER_OF_SECTORS_DIFFERS_MSG:
    db "Disk read error, number of sectors read differs from requested!" , 0

DISK_CURRENT_STATUS_MSG:
    db "Disk status:" , 0

The calling code:

; Read some sectors from the boot disk using our disk_read function
[org 0x7c00]


mov [BOOT_DRIVE] , dl

mov bp , 0x8000
mov sp , bp 
mov bx , 0x9000

mov dh , 3  ; Load 3 sectors to 0x0000 (ES):0x9000 (BX)
            ; from the boot disk.

mov dl , [BOOT_DRIVE]
call disk_read

mov dx , [0x9000]
call print_hex  ; Print out the first loaded word , which
                ; we expect to be 0xdada , stored
                ; at address 0x9000

mov dx , [0x9000+512]   ; Also , print the first word from the
call print_hex          ; 2 nd loaded sector : should be 0xface
jmp $

%include "print_string.asm" 
%include "print_hex.asm"    
%include "disk_read.asm"

; Global variables
BOOT_DRIVE: db 0

; Bootsector padding
times 510-($-$$) db 0
dw 0xaa55

times 256 dw 0xdada
times 256 dw 0xface

Result

Why first disk status 0x0380 and how to fix this timeout error (error codes were checked from here: http://www.ctyme.com/intr/rb-0606.htm)? Hard drive is of SSD type, but probably it's not relevant here since addressing back-portable to regular drives (NASM: how to access ssd drive correctly?). Update print_string:

; Print string function, note that this code written after jmp $ instruction,
; otherwise the string were printed twice
print_string:
    push ax     ; pushing two registers that used onto a stack
    push bx

    mov ah , 0x0e       ; int 10/ ah = 0 eh -> scrolling teletype BIOS routine

    loop:
        mov al, [bx]    ; put ascii value in bx (lower bits) into al
        int 0x10        ; print what in al
        inc bx          ; increment bx through the string
        cmp al, 0       ; check if passed null-terminator
        jnz loop        ; loop until null terminator met

    mov al, 0x0a    ; line feed and carriage return added after line
    int 0x10
    mov al, 0x0d
    int 0x10

    pop bx ; popping two registers that used from stack
    pop ax
    ret

print_hex:

; Print hex function, note that this code written after jmp $ instruction,
; otherwise the string were printed twice
print_hex:
    push ax     ; pushing registers that used onto a stack
    push dx
    push bx
    push cx
    push si

    mov si, 4
    mov bx, dx

    print_hex_loop:
        dec si
        cmp si, -1
        je print_hex_loop_exit
        mov dx, 0
        mov ax, bx
        mov cx, 16
        div cx
        mov bx, ax
        mov ah, 0x0e    ; int 10/ ah = 0 eh -> scrolling teletype BIOS routine
        add dx, 0x0030
        cmp dx, 0x0039
        jg add_0x27_to_letter

    print_hex_loop_continue:
        mov al, dl
        ;int 0x10       ; print what in al
        mov [HEX_OUTPUT_STR+si+2], al
        jmp print_hex_loop

    add_0x27_to_letter:
        add dx, 0x0027
        jmp print_hex_loop_continue

    print_hex_loop_exit:
        mov bx, HEX_OUTPUT_STR
        call print_string

    pop si ; popping registers that used from stack
    pop cx  ; popping registers that used from stack
    pop bx
    pop dx
    pop ax
    ret

HEX_OUTPUT_STR:
    db "0x0000", 0

Update 2: After fixing print_hex function to print with dx and not bx (in disk_read.asm) (carefully pushed and popped from stack near use), and changing from int 13/ah=0x42 to int 13/ah=0x02 (otherwise I was getting status 01h="invalid function in AH or invalid parameter"), I've got disk status 0Ch which is "unsupported track or invalid media". Any thoughts why it can be?

stackoverflower
  • 545
  • 1
  • 5
  • 21
  • You seem to have misunderstood Brendan's answer to the question you've linked. – Ross Ridge Dec 14 '19 at 20:39
  • Also you forgot to show `print_string` and `print_hex` ... those might clobber the value you want to print. – Jester Dec 14 '19 at 20:46
  • You forgot to zero `DS` too. – Jester Dec 14 '19 at 20:53
  • Why to zero DS? Since [org 0x7c00] used ... – stackoverflower Dec 14 '19 at 21:04
  • 2
    That is the actual reason ... `org 0x7c00` assumes `DS=0` so you should set it. In this case it works because you are seeing your strings but it might not work on other systems. – Jester Dec 14 '19 at 21:06
  • Just tried this code with `mov ax, 0\n mov ds, ax` lines after `org` directive, but result is the same.. – stackoverflower Dec 14 '19 at 21:13
  • Not sure what code you are running, disk status can not possibly be `0380` because you do `mov bx, 0; mov bl , ah` which zeroes the top 16 bits. – Jester Dec 14 '19 at 21:21
  • No, the second status code print is working correctly with the same assembly code. I use exact nasm code that listed (except added two lines from previous comment to zeroize DS) – stackoverflower Dec 14 '19 at 21:24
  • Why does your `print_hex` have a `mov bx, dx` in it? As it is it's not printing `bx` but `dx`. So either fix the caller or remove that. PS: learn to use a debugger. – Jester Dec 15 '19 at 00:37
  • Because it is printing dx, yes, and then I need to make sure that dx is zero for div instruction, so I preserve it. I'll fix that, but I am in doubt that this is the reason for the bug. – stackoverflower Dec 15 '19 at 07:50
  • 2
    That **is** the reason for the bug - you are not printing the disk status because you put that into `bx` not `dx`. – Jester Dec 15 '19 at 12:03
  • Thank you, didn't see that I used bx instead dx for `print_hex`. – stackoverflower Dec 15 '19 at 14:55
  • I fixed anything I could and provided more info in `Update 2` part. – stackoverflower Dec 15 '19 at 15:31
  • 1
    Some BIOSes (for example the one in my qemu installation) don't like to read multiple sectors. Try one by one, that worked for me. Also make sure your print fixes did not corrupt `dx` as that contains the number of sectors and the drive number. – Jester Dec 15 '19 at 16:45
  • @stackoverflower Please ask a new question with a [mcve] for your new problem instead of tacking it into an update. Each question should only contain one question. – fuz Dec 15 '19 at 19:40
  • 1
    @fuz okay, thanks, I'll do more efforts to fix code and if no luck - a new question with simpler code – stackoverflower Dec 15 '19 at 20:25
  • 2
    Actually, the code you showed only defines two additional sectors so no wonder trying to read 3 doesn't work :) Two works just fine. – Jester Dec 16 '19 at 19:07
  • 1
    @Jester yes, it was actually the reason of error "unsupported track or invalid media", and I must say that I fixed this code to work (added **ds,ss,es** zeroizing, removed mess with **bx** register and changed number of sectors to read to 2). – stackoverflower Dec 17 '19 at 13:08

0 Answers0