问题
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
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?
来源:https://stackoverflow.com/questions/59338886/nasm-disk-read-timeout