项目地址
经过一个学期的学习,勉强照着书本弄了一个辣鸡系统。不过跟作者的环境不同,仍然有一些需要自己改进的地方。比如引导分区的IO。
硬盘IO方式
使用硬盘IO的方式需要在bochs的配置文件中将输入文件改为硬盘类型,如下
boot: disk
# no floppyb
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="./img/boot.img"
然后镜像会以硬盘方式挂载。之后可以使用in、out指令操控它的输入输出,并且方便之处在于,不需要进行CHS的转换,直接给出逻辑扇区号就可以了。
指令使用
使用方式参考
原文已经讲清楚了用法,这里展示我的源码
SecCnt equ 0x1f2
LBALow equ 0x1f3
LBAMID equ 0x1f4
LBAHIGH equ 0x1f5
DEVICE equ 0x1f6
COMMAND equ 0x1f7
DISKDATA equ 0x1f0
; cx 扇区数
; bx 逻辑号
; di 写入位置
Read_Disk:
; 读取扇区数
mov al, cl
mov dx, SecCnt
out dx, al
; LBA 地址
; 低地址
mov al, bl
mov dx, LBALow
out dx, al
; 中地址
shr ebx, 8
mov al, bl
mov dx, LBAMID
out dx, al
; 高地址
shr ebx, 8
mov al, bl
mov dx, LBAHIGH
out dx, al
; 高四位
shr ebx, 8
and bl, 0x0f
or bl, 0xe0
mov al, bl
mov dx, DEVICE
out dx, al
; 设置 command,读取扇区
mov al, 0x20
mov dx, COMMAND
out dx, al
.check_disk:
; 检查磁盘状态
in al, dx
and al,0x88 ;第4位为1表示硬盘准备好数据传输,第7位为1表示硬盘忙
cmp al,0x08
jne .check_disk
;
mov ax, cx
mov dx, 256
mul dx
mov cx, ax
mov bx, di
mov dx, DISKDATA
.read_data:
in ax, dx
mov [bx], ax
add bx, 2
loop .read_data
ret
总体逻辑还是比较简单,封装称一个函数形式后可以重复使用
读取FAT12文件格式
这部分为是想换成FAT16的,不过挂载拷贝文件后发现还是FAT12格式,只好将就了。
如果你知道怎么整成FAT16请务必告诉我读取文件系统的思路是先读取目录,文件存在则将FAT表全部拷贝下来,因为FAT12的表项是1.5个字节,所以需要判断簇号的奇偶行来读取
; si 存放文件名地址
; di 目标位置
TmpFile equ 0x500
BaseOfRootDir equ 19
SectorOfRoot equ 14
DataOffset equ 17
Search_File:
mov [.DesIndex], di
push si
mov cx, 1
mov bx, BaseOfRootDir
mov di, TmpFile
call Read_Disk
pop si
mov cx, 0
mov dx, 0
.read_one_sector: ; 读取一个扇区,一个扇区16个表项,用 CX 计数
mov di, TmpFile
cmp cx, 16
je .one_sector_finish
mov ax, 32
mov bx, cx
mul bx
add di, ax
inc cx
mov bx, -1
.cmp_name: ; 比较文件名,长度为11
inc bx
cmp bx, 11
jz .find_filename
mov al, byte [si + bx]
cmp al, byte [di + bx]
jz .cmp_name
jmp .read_one_sector
.one_sector_finish: ; dx 记录已读目录项数
inc dx
cmp dx, SectorOfRoot
jz .search_fail
push si
push cx
push dx
mov bx, BaseOfRootDir
add bx, dx
mov di, TmpFile
call Read_Disk
pop dx
pop cx
pop si
jmp .read_one_sector
.find_filename: ; 查找成功后找寻起始簇号
push di
mov si, .ReadSuccess
call .print
pop di
add di, 0x1a
mov ax, word [di]
mov [.FATEntry], ax
call .copy_file
ret
.copy_file:
; 先将 FAT 表放进 0x500
mov si, word [.FATEntry]
push si
mov cx, 9
mov bx, 1
mov di, TmpFile
call Read_Disk
pop si
and si, 0xff
mov bx, si
.copy:
push bx
add bx, SectorOfRoot
add bx, DataOffset
push bx
; 读取一个扇区打印一个点
mov ah, 0x0e
mov al, .
int 10h
pop bx
mov cx, 1
mov di, [.DesIndex]
call Read_Disk
add word [.DesIndex], 0x200
pop cx
mov ax, 3
mul cx
mov bx, 2
div bx
add ax, TmpFile
mov di, ax
mov bx, word [di]
; 判断奇偶性
cmp dx, 0
jz .next
shr bx, 4
.next:
; 如果属于正常文件,则继续进行读取
and bx, 0x0fff
cmp bx, 0xff8
jge .copy_finish
jmp .copy
.copy_finish:
mov si, .CopyFinish
call .print
ret
.search_fail:
mov si, .ReadFail
call .print
ret
.print:
mov ah, 0x0e
mov al, [si]
cmp al, 0
jnz .continue
ret
.continue:
inc si
int 10h
jmp .print
.ReadFail db "Read Fail", 0
.ReadSuccess db "Read Success", 0
.CopyFinish db "CopyFinish", 0
.FATEntry dw 0
.DesIndex dw 0
这里使用了一些小技巧,把一些参数存在事先定义好的变量中,随时存取。两个文件加起来已经接近512字节了,原本函数还有其他输出,不过超过了512字节,所以取消了。
0 留言