📄 fat16.asm
字号:
;文 件 名: fat16.asm
;版 本: Beta 0.0.01
;功 能: 读入 kernel.sys 及 FAT16.DRVv(fat12) 到内存中,并执行kernel.sys
;编 译: nasm -fbin fat16.asm -o fat16.bin
;程 序: 姜勇/sevek/sevekwl
;注 释: 姜勇/sevek/sevekwl
;说 明:
; |-----------------------|0000:0000
; | |
; | 中断向量表 |
; | |
; |-----------------------|0000:0400
; | BIOS数据区 |
; |-----------------------|0000:0500
; | |
; | |
; | |
; | |0000:7BF4 之上区域为缓冲和堆栈
; | 引导记录 |0000:7BF8 [BP-24] = FS.DRV 链表指针
; | 堆栈区域 |0000:7BFC [BP-20] = KERNEL.SYS 链表指针
; | |0000:7BF0 [BP-16] = 根目录占用扇区数
; | |0000:7BF4 [BP-12] = 数据区起始扇区号
; | |0000:7BF8 [BP-08] = 根目录起始扇区号
; | |0000:7BFC [BP-04] = FAT表起始扇区号
; |-----------------------|0000:7C00
; | fat32引导代码 |
; |-----------------------|0000:8400
; | fat32引导代码 |
; |-----------------------|1000:0000
; | |该地址区域在装载文件之
; | KERNEL.SYS |前用于临时存放 FAT 表
; | |及根目录文件登记表等
; |-----------------------|5000:0000
; | fat32.DRV |
; |-----------------------|
; | |
; | |
; 1010部落姜勇
; 于2006年12月24日
;==================================================================================
%include ".\language\chinese.inc"
%include ".\inc\BOOTFILE.INC"
%include ".\inc\define.inc"
org Reg_IP_Base
real_boot:
;==================================================================================
jmp short BootStart ;跳转指令,转到0000:7C3E
nop
;==================================================================================
;软盘BPB表的数据定义
@OemStr DB 'MSWIN4.1' ; 8字节
SectSize DW 0x200 ; 字节/扇区 2字节
SectOfCurs DB 8 ; 每个簇占用扇区数 1字节
ResaveSect DW 8 ; 保留扇区数 2字节
FatOfDisk DB 2 ; 有几个FAT表 1字节
FileOfRoot DW 0x200 ; 根目录文件个数 2字节
SectOfDisk DW 0 ; 磁盘总扇区数 2字节
DiskType DB 0f8h ; 磁盘介质描述: 1字节
SectPreFat DW 0xcc ; 每个FAT占用扇区数 2字节
SectOfCly DW 0x3f ; 每道扇区数 2字节
DiskHeads DW 0xff ; 磁盘柱面数 2字节
HidSectors DD 0x3f ; 隐含扇区数 4字节
AllSectors DD 0x65f5b ; 大容量磁盘的总扇区数 4字节
NOfDriver DB 0x80 ; 驱动器号 1字节
ExtBootFlag DW 0x2900 ; 扩展引导标志 2字节
SerNumber DD 0x42581cf8 ; 磁盘序列号 4字节
@DiskVolume DB 'FANS BOOT01' ; 磁盘卷标 11字节
@FatType DB 'FAT16 ' ; 文件分配表类型 8字节
;==================================================================================
BootStart:
mov bp, Reg_IP_Base ;在该程序中,除发生错误外
; BP==0x7C00
mov bx, cs
cli
mov ss, bx
mov sp, bp
sti
push cs
pop ds
push cs
pop es
;==================================================================================
;检测扩展int13h
;int 0x13
;入口: AH=0x41 功能:
; BX=0x55aa 检测某驱动器是否支持
; DL=驱动器号 扩展INT 0x13
;出口: 成功 CF=0 BIOS支持扩展INT 0x13
; BX=0xAA55 并且该驱动器支持int 0x13的扩展功能
; CX=子集位图 至少支持第一个子集
; 失败 CF=1
; 或 BX!=0xAA55
; 或 CL&1!=1
;==================================================================================
mov dl, [NOfDriver] ;取驱动器号
mov ah, 0x41
mov bx, 0x55aa
int 0x13
jc LoadSecend
cmp bx, 0xaa55
jnz LoadSecend
test cl, 1
jz LoadSecend
mov byte [bp+2], 0x5a ;[BP+02]=0x5a 原为 NOP 语
;句在此借作系统是否支持扩
;展INT13H的标志,该标记将
;在Read_Disk过程中被使用。
;==================================================================================
;将Boot代码的第2扇区装载到 0000:7E00 (16进制)
;==================================================================================
LoadSecend:
mov eax, [bp+HidSectors-Reg_IP_Base]
;取隐藏扇区数
inc eax ;第2扇区号=隐藏扇区数+1
mov bx, Reg_IP_Base+0x200
mov cx, 1
call Read_Disk
jc SectorError
mov bx, SectorFlag+1
;==================================================================================
;标志检测
;该标志为 Fans Bootsector 的固有标志,总共4字节,其值必须为46,61,55,AA
;仅检测中间2字节,即:61,55
;==================================================================================
mov ax, 0x5561
cmp ax, [bx]
jnz SectorError ;标志不正确则引导失败
jmp near BeginSecend
SectorError: ;错误处理
mov si, ERR_DSK_EN
push cs
pop ds
.@@1:
lodsb
mov ah, 0x0e
int 0x10
cmp al, '!' ;检测字符串是否结束
jnz .@@1 ;重复操作
BootFail: ;引导失败,等待按键并重新引导
xor ax, ax
int 0x16
int 0x18
;==================================================================================
; | |
; sp-18 >|----------------|<<<<<<< stack low address
; | DS |
; Packet start----> sp-16 >|----------------|
; |数据包大小10字节|<-----push word 0x10 2bytes
; sp-14 >|----------------|
; |每次循环读 1扇区|<-----push word 1 2bytes
; sp-12 >|----------------|
; | 偏移地址 |<-----bx 4bytes
; sp-08 >|----------------|
; | 段 |<-----es 2bytes
; sp-06 >|----------------|
; | 绝对扇区号 |<-----eax 4bytes
; sp-04 >|----------------|
; | 0 |<-----cs 2bytes
; sp-02 >|----------------|
; | 0 |<-----cs 2bytes
; Packet over ----> sp >|----------------|<<<<<<< stack high address
; | DX |
; |----------------|
; | DI |
; |----------------|
; | SI |
; |----------------|
; | IP |
; |----------------|
; | CS |
; |----------------|
; | stack |
;==================================================================================
; Read_Disk 功能 读磁盘扇区
; 入口: bp=0x2C00
; eax=(首)扇区号
; cx=要读的扇区数
; es:bx=缓冲区首地址
; 出口: 成功 CF=0 eax=(尾)扇区号+1
; cx=0
; es:bx=缓冲区尾地址
; 失败 CF=1
;可能改变的寄存器: eax,ebx,ecx
;未改变的寄存器有: edx,ebp,esi,edi,esp,ds,es,ss
;==================================================================================
proc Read_Disk:
push si
push di
push dx
ExtReadNext:
cmp byte [bp+2], 0x5a
jnz Use_OldInt13
;使用扩展INT13H读盘,以
; 支持大容量硬盘
push cs ;cs=0
push cs ;cs=0
push eax ;eax=绝对扇区号
push es ;读数据到指定的段
push bx ;段内的偏移
push word 1 ;读多少扇区
push word 0x10 ;说明这个数据包的大小为
; 16字节
mov si, sp
push ds
push ss
pop ds ;ds:si指向数据包的位置
push eax
mov dl, [bp+NOfDriver-Reg_IP_Base]
mov ah, 0x42 ;扩展int13h的读盘功能号
int 0x13 ;扩展读盘
pop eax
pop ds
jc Extint13_Error
add sp, 0x10 ;跳过堆栈中的数据包位置
add bx, [bp+SectSize-Reg_IP_Base]
jnc no_inc_es ;无进位,转移
mov ax, es ;有进位--->ES+1000H
add ah, 10h
mov es, ax
no_inc_es:
inc eax
loop ExtReadNext
jmp short Read_Return
Extint13_Error:
add sp, 0x10 ;跳过堆栈中的数据包位置
stc
Use_OldInt13:
Read_Return:
xor cx, cx
pop dx
pop di
pop si
ret
endp
;==================================================================================
ERR_DSK_EN db 'Load the secend boot sector error .',0x0d,0x0a
db 'Please insert a bootdisk and hit any key to contion !'
BOOTFILENAME
;==================================================================================
; ****引导扇区有效标志****
; 位置 0x2C00+0x01fe(偏移)
; 数值 0xaa55
; 说明: 该标志为引导扇区有效
; 标志,若为0xaa55则有
; 效,否则BIOS认为无效
; 且不予执行。
; 注: 在本程序的其他扇区中
; 则以0xaa556146作为引
; 导扇区有效标志即:在
; 55,AA 前加上'Fa'作为
; 引导代码的次扇区有效
; 标志
times Flag_Offset+2-($-$$) db 0
dw Flag_BootSect
;**********************************************************************************
; ****引导代码第 2扇区****
; 位置 位于引导扇区之后的第
; 一扇区,由
; HidSectors+1
; 可得到其物理位置
; 说明 该部分代码用于读取其
; 他扇区并转移控制权,
; 其包含
; PrintCh
; 子过程可用于显示错误
; 提示中的汉字信息
; 另:其包含的汉字字模
; 信息被放disk_dot
; 开始的内存地址中
;==================================================================================
OtherInfo db SomeBootSectors-2 ;其他引导代码占用扇区数
dd 0x41
dd 0x42
dd 0x43
dd 0x44
dd 0x45
dd 0x46
BeginSecend:
mov si, OtherInfo+1
mov bx, Reg_IP_Base+0x400 ;BX=7c00+400=8000(Hex)
;跳过前2扇区内存区域
movzx di, [OtherInfo] ;取扇区数
push di
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -