2015-12-13 19 views
1

我想在x86程序集(16位实模式)中创建一个简单的第二阶段命令系统。函数com_dir假设在扇区以字母'F'开始时读取720KB软盘和打印字符串。FLOPPY:读取()在软盘映像返回0

这里是第二个阶段:

[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

[FLOPPY] read() on floppy image returns 0 

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这个错误

有人可以向我解释什么是错的?

注意:请忽略com_open,它仍在开发中。

+0

720K软盘有每磁道9个扇区(缸)不是18(0×12)。可能是因为你超过了赛道号(赛车),这是抱怨。 2个磁头* 80个磁道(磁道)* 9(扇区/磁道)*每个扇区512个字节= 737280 = 720k。看看你的代码,看起来你没有考虑到720k软盘(甚至是虚拟软盘)被认为是双面的(2头),所以你应该在_DH_(头号)中处理值。 –

+0

@Michael Petch用0x09代替0x12,它仍然显示相同的错误。我会研究那个(LBA给CHS)。 – RainingComputers

+0

@迈克尔佩奇是的,他们这样做。他们使用BX寄存器作为参数。 – RainingComputers

回答

1

错误:

read() on floppy image returns 0

建议Bochs的试图读取从磁盘图像数据,但它试图访问该盘中的部分没有实际存在。如果您创建的磁盘映像小于正在使用的软盘驱动器类型,并且您没有使用自动媒体格式,则可能发生在Bochs中。

有几种方法可以解决这个问题。在Bochs中将Type of floppy drive设置为720K,将Type of floppy media设置为720K。由于您的磁盘映像是720k,所以这种更改应该会导致此错误消失。

另一种方法是将Type of floppy drive设置为2.88MB驱动器,然后将Type of floppy media设置为auto。在现实世界中一个2.88MB的软盘驱动器也可以读取1.44MB,720K,360K,180K和3.5" 的媒体。Bochs的尝试与AUTO软盘介质类型来模拟这一点。

如果你的磁盘映像是720K和使用AUTO媒体,Bochs会自动下拉到你实际使用的磁盘映像的大小,唯一的要求是磁盘映像是正好是180k,360k,720k,1440k,2880k)中的一个。已知标准3.5英寸磁盘的大小将无法正常工作AUTO


在你原来的问题的代码这样做:

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

如果使用3.5" 720K媒体,每个柱面的扇区数为09(不是0×12)有软盘的好表你的代码不应该尝试读取比媒体允许的扇区更高的扇区,Bochs会抛出一个类似于的错误,尝试读/写扇区xx,超过最后一个扇区x。看起来像这样:

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


增加缸,我建议你考虑创建一个LBA(逻辑块寻址),以CHS程序(和反之亦然)。 LBA编号只是从0到驱动器上的扇区数的扇区编号。例如,一张720k软盘上有1440个512字节的扇区。因此,LBA从0到1439.您可以使用此Wiki article下的第二个公式将任何LBA转换为CHS(气缸盖扇区)值。

CHS tuples can be mapped to LBA address with the following formula:[5][6]

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

where

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 addresses can be mapped to CHS tuples with the following formula ("mod" is the modulo operation, i.e. the remainder, and "÷" is integer division, i.e. the quotient of the division where any fractional part is discarded):

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

实施第二函数(LBA转换到CHS),你可以再循环从0到1439,每个LBA转换为CHS,然后调用读取扇区功能。如果你打算浏览类似DOS的FAT12FAT16磁盘格式等。这将是非常有用的

相关问题