簡體   English   中英

FLOPPY:軟盤映像上的read()返回0

[英]FLOPPY: read() on floppy image returns 0

我正在嘗試在x86匯編(16位實模式)中創建一個簡單的第二階段命令系統。 假定函數com_dir讀取720KB的軟盤並在扇區以字母'F'開頭時打印字符串。

這是第二階段:

[BITS 16]
[ORG 0x0000]      

mov ax, cs
mov ds, ax   
mov [drive_num], dl
mov [root_drive], dl
mov bx, load_msg
call str_prt
call new_line
call new_line
xor cx, cx  
call new_line
mov bx, art1
call str_prt
call new_line
mov bx, art2
call str_prt
call new_line
mov bx, art3
call str_prt
call new_line
mov bx, art4
call str_prt
call new_line
mov bx, art5
call str_prt
call new_line
mov bx, art6
call str_prt
call new_line
mov bx, art7
call str_prt
call new_line
mov bx, welcome_msg
call str_prt
call new_line
mov bx, creator_msg
call str_prt
call new_line
mov bx, boot_msg
call str_prt
call new_line

mov bx, [buffer]

call new_line

mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
mov al, '>'
int 0x10

loop:
xor ah, ah
int 0x16
call key_scan
jmp loop

%include "util.inc"

pro_com:
push bx
push ax
mov bx, buffer
mov al, [bx]
cmp al, 'h'
jne help_end
inc bx
mov al, [bx]
cmp al, 'e'
jne help_end
inc bx
mov al, [bx]
cmp al, 'l'
jne help_end
inc bx
mov al, [bx]
cmp al, 'p'
jne help_end
call com_help
jmp pro_end
help_end:
mov bx, buffer
mov al, [bx]
cmp al, 'd'
jne dir_end
inc bx
mov al, [bx]
cmp al, 'i'
jne dir_end
inc bx
mov al, [bx]
cmp al, 'r'
jne dir_end
call com_dir
jmp pro_end
dir_end:
mov bx, buffer
mov al, [bx]
cmp al, 'o'
jne open_end
inc bx
mov al, [bx]
cmp al, 'p'
jne open_end
inc bx
mov al, [bx]
cmp al, 'e'
jne open_end
inc bx
mov al, [bx]
cmp al, 'n'
jne open_end
call com_open
jmp pro_end
open_end:
mov bx, not_found
call str_prt
call new_line
pro_end:
pop ax
pop bx
ret

com_help:
push bx
call new_line
call draw_line
mov bx, dir_help
call str_prt
call new_line
call draw_line
call new_line
pop bx
ret

com_dir:
push ax
push bx
push cx
push dx
call new_line
call draw_line
mov bx, drive_num
mov dl, [bx]
mov al, 0x01
mov ch, 0x00
mov cl, 0x01
mov dh, 0x00
com_dir_loop:
call read_dir
cmp cl, 0x12
je false1
inc cl
jmp com_dir_loop
false1:
cmp ch, 0x4f
je false2
inc ch
xor cl, cl
add cl, 0x01
jmp com_dir_loop
false2:
call draw_line
call new_line
pop dx
pop cx
pop bx
pop ax 
ret

read_dir:
push ax
push bx
mov bx, 0x1000
mov es, bx
mov bx, 0xe00
call read_disc
clc
mov bx, 0x0e00
mov al, [bx]
cmp al, 'F'
jne read_dir_end
mov bx, 0x0e01
call str_prt
call new_line
read_dir_end:
pop bx
pop ax 
mov bx, 0x1000
mov es, bx
ret

com_open:
push ax
push bx
push cx
push dx
mov bx, drive_num
mov dl, [bx]
mov cl, 0x00
mov al, 0x01
mov dh, 0x00
mov bx, 0x1000
mov es, bx
mov ch, 0x00
mov cl, 0x09
mov bx, 0xe00
;----------
com_open_loop:
call read_disc
call next_load
jc com_open_loop_end
jmp com_open_loop
;----------
com_open_loop_end:
clc
call 0x0e0d
clc
call new_line
mov bx, 0x1000
mov es, bx
mov ds, bx
pop dx
pop cx
pop bx
pop ax 
ret

next_load:

clc
ret

buffer times 20 db 0

drive_num:
db 0
root_drive:
db 0

welcome_msg:
db 'Welcome to matriXos$'
creator_msg:
db 'Created by Vishnu Shankar.B$'
boot_msg:
db 'Booting command line interface...$'
not_found:
db '<Error>Command cannot be resolved! Use command "help"$'
dir_help:
db '    dir - Lists files in a drive$'
line:
db '==============================$'
art1:
db '            ==       ==$'
art2:
db '            #  X   X  #$'
art3:
db '            #   X X   #$'
art4:
db '            #    X    #$'
art5:
db '            #   X X   #$'
art6:
db '            #  X   X  #$'
art7:
db '            ==       ==$'
load_msg:
db 'Successfully loaded operating system$'

jmp $
times 3584 - ($ - $$) db 0

我的文件util.inc

key_scan:
cmp al, 0x08
je back_space
cmp al, 0x0d
je enter
cmp cx, 0x0015 
je end
mov ah, 0x0e
int 0x10
mov bx, buffer
add bx, cx
mov [bx], al
inc cx
jmp end
back_space:
cmp cx, 0x00
je end
dec cx
mov ah, 0x0e
mov al, 0x08
int 0x10
mov al, 0x20
int 0x10
mov al, 0x08
int 0x10
jmp end
enter:
xor cx, cx
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
call pro_com
call clear_buffer
mov ah, 0x0e
mov al, '>'
int 0x10
end:
ret

clear_buffer:
push ax
push bx
push cx
mov bx, buffer
xor cx, cx
xor ax, ax
start:
cmp cx, 0x41
je end_buff
mov [bx], ax
inc bx
inc cx
jmp start
end_buff:
pop cx
pop bx
pop ax
ret

str_prt:
pusha
str:
mov ah, 0x0e
mov al, [bx]
cmp al, '$'
je str_end
int 0x10
add bx, 1
jmp str
str_end:
popa
ret

draw_line:
push ax
push bx
line_str:
mov bx, line
call str_prt
call new_line
pop bx
pop ax
ret

new_line:
push ax
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
pop ax
ret

read_disc:
mov ah, 0x02   
int 0x13   
ret

hex_print:
push ax
push cx
mov ah, 0x0e
mov al, '0'
int 0x10
mov al, 'x'
int 0x10
hex_print_start:
mov al, ch
and al, 0xf0
call hex_map
int 0x10
shl cx, 0x04
mov al, ch
and al, 0xf0
call hex_map
int 0x10
shl cx, 0x04
mov al, ch
and al, 0xf0
call hex_map
int 0x10
shl cx, 0x04
mov al, ch
and al, 0xf0
call hex_map
int 0x10
hex_print_end:
pop cx
pop ax
ret

hex_map:
cmp al, 0x00
jne zero_end
mov al, '0'
ret
zero_end:
cmp al, 0x10
jne one_end
mov al, '1'
ret
one_end:
cmp al, 0x20
jne two_end
mov al, '2'
ret
two_end:
cmp al, 0x30
jne three_end
mov al, '3'
ret
three_end:
cmp al, 0x40
jne four_end
mov al, '4'
ret
four_end:
cmp al, 0x50
jne five_end
mov al, '5'
ret
five_end:
cmp al, 0x60
jne six_end
mov al, '6'
ret
six_end:
cmp al, 0x70
jne seven_end
mov al, '7'
ret
seven_end:
cmp al, 0x80
jne eight_end
mov al, '8'
ret
eight_end:
cmp al, 0x90
jne nine_end
mov al, '9'
ret
nine_end:
cmp al, 0xa0
jne a_end
mov al, 'A'
ret
a_end:
cmp al, 0xb0
jne b_end
mov al, 'B'
ret
b_end:
cmp al, 0xc0
jne c_end
mov al, 'C'
ret
c_end:
cmp al, 0xd0
jne d_end
mov al, 'D'
ret
d_end:
cmp al, 0xe0
jne e_end
mov al, 'E'
ret
e_end:
cmp al, 0xf0
jne f_end
mov al, 'F'
ret
f_end:
ret

由於某些原因,當讀取720KB(720次)時,它將在bochs中引發此錯誤:

[FLOPPY] read() on floppy image returns 0

有人可以向我解釋什么地方不對嗎?

注意:請忽略com_open ,它仍在開發中。

錯誤:

軟盤映像上的read()返回0

建議Bochs嘗試從磁盤映像讀取數據,但是它試圖訪問的磁盤部分實際上並不存在。 如果您創建的磁盤映像小於所使用的軟盤驅動器類型,並且未使用自動媒體格式,則在Bochs中可能會發生這種情況。

您有兩種方法可以解決此問題。 在Bochs中將Type of floppy driveType of floppy drive設置為720K,將Type of floppy mediaType of floppy media為720K。 由於您的磁盤映像為720k,因此更改將導致此錯誤消失。

另一種方法是將Type of floppy driveType of floppy drive設置為2.88MB驅動器,然后將Type of floppy mediaType of floppy media設置為auto 在現實世界中,一個2.88MB的軟盤驅動器還可以讀取1.44MB,720K,360k和180k的3.5“介質。Bochs嘗試使用AUTO軟盤介質類型對此進行模擬。

如果您的磁盤映像為720K並使用AUTO介質,則Bochs會自動降低到實際使用的磁盤映像的大小。 唯一的要求是磁盤映像必須是正好180k,360k,720k,1440k,2880k之一。 AUTO不能正常使用任何已知標准3.5英寸磁盤的大小。


您原始問題中的代碼是這樣做的:

com_dir_loop:
call read_dir
cmp cl, 0x12       ; 0x12=18 decimal. CL=sector number

如果使用3.5英寸720k介質,則每個柱面的扇區數為0x09(而不是0x12)。此Wiki文章中有一張不錯的軟盤幾何表。您的代碼不應嘗試讀取比介質允許的扇區高的扇區。 Bochs將引發另一種類型的錯誤,類似於嘗試在最后一個扇區x之后讀取/寫入扇區xx,您的代碼如下所示:

com_dir_loop:
call read_dir
cmp cl, 0x09       ; CL=sector number

在圖表中,對於720k軟盤(在給定的鏈接處),您將觀察到的另一件事是720K軟盤有2個磁頭(0和1)。 您的代碼僅處理頭0。這意味着您的代碼將只能訪問磁盤內容的一半。 頭1上的任何內容都將被忽略。 您將需要處理DH中的磁頭,以便在達到每個汽缸(磁道)限制的扇區時,將磁頭增加1。如果超過2磁頭限制,則必須將扇區調整回1。然后返回0並將圓柱增加1。


由於您似乎正在編寫內核的各個部分,因此建議您考慮為CHS例程創建一個LBA(邏輯塊尋址)(反之亦然)。 LBA號只是一個從0到驅動器上的扇區數的扇區號。 例如,在720k軟盤上有1440 512字節的扇區。 因此LBA從0到1439。您可以使用此Wiki文章下的第二個公式將任何LBA轉換為CHS(氣缸蓋扇區)值。

可以使用以下公式將CHS元組映射到LBA地址:[5] [6]

 LBA = (C × HPC + H) × SPT + (S - 1) 

哪里

 C, H and S are the cylinder number, the head number, and the sector number LBA is the logical block address HPC is the maximum number of heads per cylinder (reported by disk drive, typically 16 for 28-bit LBA) SPT is the maximum number of sectors per track (reported by disk drive, typically 63 for 28-bit LBA) 

可以使用以下公式將LBA地址映射到CHS元組(“ mod”是模運算,即余數,“÷”是整數除法,即除掉任何小數部分的除法的商):

 C = LBA ÷ (HPC × SPT) H = (LBA ÷ SPT) mod HPC S = (LBA mod SPT) + 1 

實現第二個功能(將LBA轉換為CHS),然后可以從0循環到1439,將每個LBA轉換為CHS,然后調用讀取扇區功能。 如果您打算瀏覽DOS的FAT12FAT16磁盤格式等內容,這將非常有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM