;##########################################################################
; 这是一段引导程序,本程序是将加载程序加载至 9000:0100 处,
; 并将控制权转移到加载程序。
; 本代码使用 NASM 进行编译。
;##########################################################################
; * 本文档代码仅适用 [软驱] 启动 *
;--------------------------------------------------------------------------
org 07c00h ; Boot 状态, Bios 将把 Boot Sector 加载到 0:7C00 处并开始执行
[bits 16] ; 定义以下代码生成为16位代码。
;==================================================================
; 常量定义
;==================================================================
BaseOfStack equ 07c00h ; 引导程序开始地址,堆栈的顶部。
; 加载程序地址
BaseOfLoader equ 09000h ; LOADER.com 被加载到的位置 ---- 段地址
OffsetOfLoader equ 0100h ; LOADER.com 被加载到的位置 ---- 偏移地址
; 读取 FAT 软盘所需的常量
RootDirSectors equ 14 ; 根目录占用空间
SectorNoOfRootDirectory equ 19 ; 根目录的第一个扇区号
SectorNoOfFAT1 equ 1 ; FAT1 的第一个扇区号 = BPB_RsvdSecCnt
DeltaSectorNo equ 17 ; DeltaSectorNo = BPB_RsvdSecCnt +(BPB_NumFATs * FATSz)-2
; 文件的开始Sector号 = DirEntry中的开始Sector号 + 根目录
; 占用Sector数目 + DeltaSectorNo
;==================================================================
jmp short LABEL_START ; 跳转至程序开始处。
nop ; 这个 nop 不可少,为确保Fat12格式。
;==================================================================
;==================================================================
; 以下是FAT12格式的数据头。
BS_OEMName DB 'ForrestY' ; OEM String, 必须 8 个字节
BPB_BytsPerSec DW 512 ; 每扇区字节数
BPB_SecPerClus DB 1 ; 每簇多少扇区
BPB_RsvdSecCnt DW 1 ; Boot 记录占用多少扇区
BPB_NumFATs DB 2 ; 共有多少 FAT 表
BPB_RootEntCnt DW 224 ; 根目录文件数最大值
BPB_TotSec16 DW 2880 ; 逻辑扇区总数
BPB_Media DB 0xF0 ; 媒体描述符
BPB_FATSz16 DW 9 ; 每FAT扇区数
BPB_SecPerTrk DW 18 ; 每磁道扇区数
BPB_NumHeads DW 2 ; 磁头数(面数)
BPB_HiddSec DD 0 ; 隐藏扇区数
BPB_TotSec32 DD 0 ;如果 wTotalSectorCount 是 0 由这个值记录扇区数
BS_DrvNum DB 0 ;中断 13 的驱动器号,即启动驱动器号
BS_Reserved1 DB 0 ; 未使用
BS_BootSig DB 29h ; 扩展引导标记 (29h)
BS_VolID DD 0 ; 卷序列号
BS_VolLab DB 'Xos System '; 卷标, 必须 11 个字节
BS_FileSysType DB 'FAT12 ' ; 文件系统类型, 必须 8个字节
;==================================================================
; #############################
; # 主程序代码开始 #
; #############################
LABEL_START:
mov ax, cs
; 取代码所在段,其他段均与代码段一致。因为在16位下,只能寻址64K范围。
mov ds, ax ; 数据段
mov es, ax ; 附加段
mov ss, ax ; 堆栈段
mov sp, BaseOfStack
; 堆栈基地址。一般情况,此时的堆栈只是临时的,到了加载模块时还要重新设置,
; 由其是进入32位代码模块后,才是最重要的。
mov [0523h], dl ; 保存启动盘号,A盘为0,硬盘C为80
; 开机后,启动盘号由BIOS保存至寄存器dl中。
;####################################################
; 清屏
;----------------------------------------------------
mov ax, 0600h ; AH = 6, AL = 0h
mov bx, 0700h ; 黑底白字(BL = 07h)