📄 fat12.asm
字号:
;文件名: fat12.asm
;版 本: test 0.06.12.7
;功 能: 读入 kernel.sys 及 FAT12.DRV(fat12) 到内存中,并执行kernel.sys
;编 译: nasm -fbin fat12.asm -o fat12.bin
;说 明:
; |-----------------------|0000:0000
; | |
; | 中断向量表 |
; | |
; |-----------------------|0000:0400
; | BIOS数据区 |
; |-----------------------|0000:0500
; | |
; | |
; | |0000:7BF0 之上的区域为kernel.sys与FAT12.DRV的Fat链表
; | |0000:7BF2 [BP-14] FAT12.DRV的首簇号;执行Get_FileFat后为首指针
; | 引导记录 |0000:7BF4 [BP-12] Kernel.sys的首簇号;执行Get_FileFat后为首指针
; | 堆栈区域 |0000:7BF6 [BP-10] 磁盘数据区起始位置
; | |0000:7BF8 [BP-08] 根目录占用扇区数
; | |0000:7BFA [BP-06] 根目录起始扇区号
; | |0000:7BFC [BP-04] Fat表起始扇区号
; | |0000:7BFE [BP-02] 驱动器号
; |-----------------------|0000:7C00 [BP-00]
; | Fat12引导扇区 |
; |-----------------------|0000:7E00
; | |
; | 空--未使用 |
; | |
; |-----------------------|1000:0000
; | |该地址区域在装载文件之
; | KERNEL.SYS |前用于临时存放 FAT 表
; | |及根目录文件登记表等
; |-----------------------|5000:0000
; | FAT12.DRV |
; |-----------------------|
; | |
; | |
;==================================================================================
%include ".\inc\define.inc"
%include ".\inc\bootfile.inc"
org 0x7c00
;==================================================================================
jmp short BootStart ;jmp short 0x7C3E
nop
;==================================================================================
;软盘BPB表的数据定义
@OemStr DB 'FANOS0.1' ; 8字节
SectSize DW 512 ; 字节/扇区 2字节
SectOfCurs DB 1 ; 每个簇占用扇区数 1字节
ResaveSect DW 1 ; 保留扇区数 2字节
FatOfDisk DB 2 ; 有几个FAT表 1字节
FileOfRoot DW 224 ; 根目录文件个数 2字节
SectOfDisk DW 0B40H ; 磁盘总扇区数 2字节
DiskType DB 0f0h ; 磁盘介质描述: 1字节
SectPreFat DW 9 ; 每个FAT占用扇区数 2字节
SectOfCly DW 18 ; 每道扇区数 2字节
DiskHeads DW 2 ; 磁盘柱面数 2字节
HidSectors DD 0 ; 隐含扇区数 4字节
AllSectors DD 0 ; 大容量磁盘的总扇区数 4字节
NOfDriver DB 00h ; 驱动器号 1字节
ExtBootFlag DW 29H ; 扩展引导标志 2字节
SerNumber DD 0 ; 磁盘序列号 4字节
@DiskVolume DB 'FANS BOOT ' ; 磁盘卷标 11字节
@FatType DB 'FAT12 ' ; 文件分配表类型 8字节
;==================================================================================
BootStart:
mov bp, Reg_IP_Base
mov ax, cs
mov ss, ax
mov sp, bp
push dx ; SP = 0x7bfe
; [BP-02] <- driver number
mov si, Fat12_StartMSG
call Put_Char
;==================================================================================
;获取磁盘中文件系统信息
mov si, [bp+HidSectors-0x7c00] ;
add si, [bp+ResaveSect-0x7c00] ; SI = Start Fat
push si ; SP = 0x7bfc
; [BP-04] <- Start Fat
;
sub ax, ax
mov al, [bp+FatOfDisk-0x7c00] ;
mul word [bp+SectPreFat-0x7c00] ;
add si, ax ; SI = Start Root
push si ; SP = 0x7BFA
; [BP-06] <- Start Root
mov ax, [bp+FileOfRoot-0x7c00] ;
mov bx, [bp+SectSize-0x7c00] ;
shr bx, 5 ; BX / 32
cwd
div bx ; AX = \
; 根目录占用扇区数=\
; (根目录文件数 * 每文件登记项大小|32字节|)\
; / 每扇区字节数|512字节|=\
; 根目录文件数 / (每扇区字节数 / 每文件登记项大小)
push ax ; SP = 0x7BF8
; [BP-08] <- Sector pre root
add si, ax ; SI= start data
push si; ; SP = 0X7BF6
; [BP-10] <- Start data
;==================================================================================
;查找文件
mov ax, [bp-6]
mov di, [bp-8] ; DS = CS = 0
push word Seg_CS_Boot
pop es ; ES = Seg_CS_Boot
xor bx, bx
call Read_disk
jc Error_DiskRead
mov si,BootFilename
call find_File
push ax ; SP - 0X7BF4
; [BP-12] <- KERNEL.SYS 的首簇号
jc Error_FileKernel
mov si,FileSystemDrv
call find_File
push ax ; SP = 0X7BF2
; [BP-14] <- FAT12.DRV的首簇号
jc Error_FileFsdrv
;==================================================================================
;读文件分配表到缓冲区
mov di, [bp+SectPreFat-0x7c00]
mov ax, [bp-4]
xor bx, bx
call Read_disk
jc Error_DiskRead
mov ax, [bp-12] ; 取Kernel.sys 的首簇号
mov bx, sp
dec bx
dec bx ; BX = BP - 16
mov [bp-12],bx ; [bp-12] = kernel.sys fat group
push es ; ES = Seg_CS_Boot
pop ds ; DS = Seg_CS_Boot
call Get_FileFat
mov ax, [bp-14] ; 取FAT12.DRV的首簇号
mov bx, sp
dec bx
dec bx
mov [bp-14],bx ; [BP-14] = fs.drv fat group
call Get_FileFat
;==================================================================================
;读文件
mov si, [bp-12] ; SI -> kernel.sys fat group
call Load_file
jc Error_FileKernel
mov si,[bp-14] ; si -> fs.drv fat group
push word Seg_FS_Boot
pop es
call Load_file
jc Error_FileFsdrv
mov dx, [bp-2]
db 0xea
dw 0x0,Seg_CS_Boot+0x20
;==================================================================================
Error_DiskRead:
mov si, Msg_ErrReadisk
jmp short boot_error
Error_FileFsdrv:
mov si, ERR_DRV
jmp short boot_error
Error_FileKernel:
mov si, ERR_KNL
jmp short boot_error
boot_error:
call Put_Char
mov si, Fat12_ERRMSG
call Put_Char
xor ax, ax
int 0x16
int 0x18
;==================================================================================
Put_Char:
push cs
pop ds
next_put:
lodsb ;从 ds:si中读入一个字符到 al
or al,al ;检测字符是否为0
jz put_return ;显示完毕, 退出过程
mov ah,0x0e
mov bl,9
int 0x10
jmp short next_put ;重复操作
put_return:
ret
;======================================================================================
;Load_file: 装入文件 入口 SI = 文件的FAT连表地址(反向)
;======================================================================================
Load_file:
push ss
pop ds ; DS = SS = 0
xor bx, bx
GetFatNumber:
std ; si --
lodsw
and ax, ax ; if feof
clc
jz ReadOK ; then return
ReadOneFat:
dec ax
dec ax
mov di,[bp+SectOfCurs-0x7c00]
and di,0xff
mul di
add ax, [bp-10]
call Read_disk
jnc GetFatNumber
stc
ReadOK:
ret
;======================================================================================
; Get_FileFat 获取文件的FAT链条到堆栈
; ax = 首指针
;======================================================================================
Get_FileFat:
pop di ; DI = IP of the father process
cld
FileFat_next:
push ax ; AX = pointer
mov si, ax ; FAT12:
add si, si ; Next address = pointer * 3 / 2
add si, ax ; SI = AX * 3
shr si, 1 ; SI / 2
lodsw
jnc bit_check ; if pointer % 2 = 1
shr ax, 4 ; then clear the low bit
bit_check: ; else
and ah,0x0f ; clear the high bit
cmp ax, 0xfff ; if pointer table isn't over ?
jb FileFat_next ; get next pointer
xor ax, ax ; feof
push ax ; save eof
push di ; save IP
ret
;======================================================================================
;find_File 查找文件 ds:si=文件名字偏移地址 正确:cf=0 ax=文件首簇号
; es:0x0000=根目录缓冲区 错误:cf=1 ax=无意义
;======================================================================================
find_File:
xor di,di
cld
next_Find:
push di
push si
mov cx, 11 ; size of file name
repe cmpsb
pop si
pop di
je ffind_Down
add di,32
cmp byte [es:di],0
jnz next_Find
not_found:
stc
ret
ffind_Down:
mov ax, [es:di+0x1a]
clc
ret
;======================================================================================
;ReadDisk 读磁盘 ax=绝对扇区号 正确:cf=0 读磁盘时如果超过段
; di=要读的扇区数 错误:cf=1 限制将会自动调整段
; es:bx=内存位置 并设置bx=0
;--------------------------------------------------------------------------------------
Read_disk:
push si
read_next:
push ax
mov ax, 0x0e2e
int 0x10
pop ax
push ax ;ax=绝对扇区号
xor dx, dx
div word [ bp+SectOfCly-0x7C00]
;TEMP = 绝对扇区号 / 每道扇区数
mov cx, dx ;CL = 绝对扇区号 MOD 每道扇区数 = 未调整的扇区号
xor dx, dx
div word [ bp+DiskHeads-0x7c00]
mov ch, al ;CL = TEMP /磁头数 = 磁道号
mov dh, dl ;DH = TEMP MOD 磁头数 = 磁头号
mov dl, [bp+NOfDriver-0x7c00]
inc cl
mov si, COUNT_Retry
reading_now:
mov ax, ReadOneSector
;读磁盘
int 13h
jnc read_ok ;读正确,转移
xor ax, ax
int 0x13
dec si ;不正确--->继续读,读5次返回错误处理
jnz reading_now
pop ax
pop si
stc ;设错误标志, CF = 1
ret ;返回,不再读
read_ok:
add bx, [bp+SectSize-0x7c00]
;ES:BX=读数据的位置
;每成功读数据一个扇区,BX+512
;如果计算的结果超过 0xffff,将回产生进位
jnc no_incr_es ;无进位,转移
mov ax, es ;有进位--->ES+1000H
add ah, 10h
mov es, ax
no_incr_es:
pop ax ;弹出绝对扇区号
inc ax ;绝对扇区号加1
dec di ;需要读的扇区数减1
jnz read_next ;如果没有读完(!=0),继续读下一个扇区
pop si ;读完,弹出 si
clc ;置正确标志
ret ;返回
;==================================================================================
BOOTFILENAME
Msg_ErrReadisk db 0x0d,0x0a,'DISK',0
ERR_KNL db 0x0d,0x0a,'OSLOADER.SYS',0
ERR_DRV db 0x0d,0x0a,'FS.DRV',0
Fat12_ERRMSG db ' : error!',0
Fat12_StartMSG db 'Loading',0
times Flag_Offset+2-($-$$) db 0
dw Flag_BootSect
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -