• 开源个我的 x86 架构操作系统的 boot 程序


    开发语言:汇编
    编译工具:NASM for Win
    1、BOOT.ASM
    ;************************************************************************************************
    ;
    ; Name........... Noah system boot program
    ; File........... BOOT.ASM
    ; Version........ 1.0.0
    ; Dependencies... x86
    ; Description.... for Noah system startup loader program
    ; Author......... 周文星 ( Zhou Wen Xing )
    ; CSDN Accounts.. SupermanKing
    ; Date........... Jan, 05nd 2011
    ; UpdateURL...... http://noah.rljy.com/
    ; QQ Codeing..... 44068232
    ; TEL............ +86.015677228819
    ; E-Mail......... humanhome@126.com
    ;
    ; Copyright (c) 2004-2011 by www.rljy.com
    ; LiuZhou city, China
    ;
    ;************************************************************************************************
    ;================================================================================================
    ; Program Description ( 程序描述 )
    ;================================================================================================
    ; 本程序在16位的实时模式下运行,目的为实现加载并执行 Loader 程序做启动处理
    ; 支持 FAT12 文件系统的文件检索识别处理
    ;
    ;================================================================================================
    ; Constant defining ( 常数定义 )
    ;================================================================================================
    %INCLUDE    "NS_CONSTANT.INC"
    BOOT_MODE    EQU    FD_FAT12            ; Fat12:
                                            ; Floppy installation can be used as such.
                                            ;
                                            ; Fat32:
                                            ; Harddisk installation requires modification
                                            ; of the Fat32 header, or you'll lose everything
                                            ; on the target partition.
                                            ;
                                            ; Debug:
                                            ; No Header. Use for debugging with floppy only !!
                                            ; Messages at low left corner during boot:
                                            ; 1 : bootsector loaded
                                            ; 2 : file not found
                                            ; 3 : file found - load starts
                                            ; 4 : jump to kernel
    BOOT_DRV        EQU    FD_DISK1
    
    
    ;================================================================================================
    ; Program start ( 程序开始 )
    ;================================================================================================
    $START:
        ORG ORIGIN                            ; Boot 状态, Bios 将把 Boot Sector 加载到 0:7C00 处并开始执行
        ;==================== 初始化 MBR( Master Boot Record 主引导记录 ) 表 ====================
        ;---------- BS_jmpBoot 节点 ( 3 BYTE ) ----------
        JMP MAIN                               ; ( 2 BYTE )跳转到执行程序段落
        NOP                                    ; ( 1 BYTE )这个 nop 不可少
    
    %IF BOOT_MODE == FD_FAT12
        ; 下面是 FAT12 磁盘的头
        BS_OEMName        DB 'NOAH 1.0'         ; ( 8 BYTE )厂商名, 必须 8 个字节 ( 这里标注为诺亚系统 )
        ;---------- BPB 节点( 53 BYTE ) ----------
        ; BIOS Parameter Block
        BPB_BytsPerSec    DW 512                ; ( 2 BYTE )每扇区字节数 512 个字节
        BPB_SecPerClus    DB 0x01               ; ( 1 BYTE )每扇区分配单位 ( MS DOS5.0 设置其值为 8 )
        BPB_RsvdSecCnt    DW 0x0001             ; ( 2 BYTE )Boot 记录占用多少扇区 ( MS DOS5.0 标注为保留的意思,但设置其值为 1 )
        BPB_NumFATs       DB 0x02               ; ( 1 BYTE )共有多少 FAT 表 ( 如果出现磁盘坏道,两个 FAT 表的价值才有体现 )
        BPB_RootEntCnt    DW 0x00E0             ; ( 2 BYTE )根目录文件数最大值
        BPB_TotSec16      DW 0x0B40            ; ( 2 BYTE )逻辑扇区总数 ( 高密3.5英寸软盘最高密度支持:2面×每面80磁道×每磁道18扇区 = 2880扇区 )
        BPB_Media         DB 0xF0               ; ( 1 BYTE )媒体描述符( 软盘类型,高密3.5英寸软盘,双面 )
        BPB_FATSz16       DW 0x0009             ; ( 2 BYTE )每FAT扇区数
        BPB_SecPerTrk     DW 0x0012             ; ( 2 BYTE )每磁道扇区数
        BPB_NumHeads      DW 0x0002             ; ( 2 BYTE )磁头数(面数)
        BPB_HiddSec       DD 0x00000000         ; ( 4 BYTE )隐藏扇区数
        BPB_TotSec32      DD 0x00000000         ; ( 4 BYTE )如果 wTotalSectorCount 是 0 由这个值记录扇区数
    
        BS_DrvNum         DB BOOT_DRV           ; ( 1 BYTE )中断 13 的驱动器号
        BS_Reserved1      DB 0x00               ; ( 1 BYTE )未使用
        BS_BootSig        DB 0x29               ; ( 1 BYTE )扩展引导标记 (29h)
        BS_VolID          DD 0x18073C0B         ; ( 4 BYTE )卷序列号
        BS_VolLab         DB 'NOAH SYSTEM'      ; ( 11 BYTE )卷标, 必须 11 个字节(虽然Windows读卷标具体的是在 FDT 表里)
        BS_FileSysType    DB 'FAT12   '         ; ( 8 BYTE )文件系统类型, 必须 8个字节
    %ELSE
    %IF BOOT_MODE == HD_FAT16
    
    %ELSE
    %IF BOOT_MODE == HD_FAT32
    
    %ELSE
    %IF BOOT_MODE == HD_NTFS
    
    %ENDIF
    %ENDIF
    %ENDIF
    %ENDIF
    
    
    ;---------- 引导程序代码( 420 BYTE ) ----------
    MAIN:
        ;==================== 初始化寄存器 ====================
        CLI                                  ; 停止堆栈中以前的中断
        CLD;
    
        XOR    AX, AX                        ; 将 AX 寄存器清零
        MOV    SS, AX                        ; 在堆栈的工作只在下面的程序
        MOV    AX, CS                        ; CS 代码段寄存器
        MOV    DS, AX                        ; DS 数据段寄存器
        MOV    ES, AX                        ; ES 补助段寄存器
        MOV    SS, AX                        ; SS 堆栈段寄存器
        MOV    SP, ORIGIN
    
        ;------------------------------------------------------------
        ; 加载 Loader 程序
        ;------------------------------------------------------------
        %INCLUDE    "NSRDLM.INC"
        JMP$
        ;================================================================================================
        ; Public function defining ( 公共的函数定义 )
        ;================================================================================================
        %INCLUDE    "NS_VARIABLE.INC"
        %INCLUDE    "NS_FUNCTION.INC"
        Diskformat:
        times 510-($-$$)    db    0            ; 填充剩下的空间,使生成的二进制代码恰好为512字节
        ;---------- 有效结束标志( 2 BYTE ) ----------
        dw 0xAA55                              ; 结束标志

    2、NS_CONSTANT.INC
    ;================================================================================================
    ; Constant defining ( 常数定义 )
    ;================================================================================================
    ORIGIN		EQU	7C00H				; 把 Boot Sector 加载到的起始地址
    MEMADDR		EQU	0400H				; 内存起始偏移地址
    LOADERADDR	EQU	09000H				; Loader 载入内存起始地址
    
    ; 以下为编译条件
    DEBUG		EQU	0				; 设置程序为调试模式
    FD_FAT12	EQU	1				; 设置程序为软盘的 FAT12 文件系统
    HD_FAT16	EQU	2				; 设置程序为硬盘的 FAT16 文件系统
    HD_FAT32	EQU	3				; 设置程序为硬盘的 FAT32 文件系统
    HD_NTFS		EQU	4				; 设置程序为硬盘的 NTFS  文件系统
    
    ; 最多支持 2 个软驱设备
    FD_DISK1	EQU	00h
    FD_DISK2	EQU	01h
    
    ; 最多支持 8 块硬盘
    HD_DISK1	EQU	80h
    HD_DISK2	EQU	81h
    HD_DISK3	EQU	82h
    HD_DISK4	EQU	83h
    HD_DISK5	EQU	84h
    HD_DISK6	EQU	85h
    HD_DISK7	EQU	86h
    HD_DISK8	EQU	87h

    3、NSRDLM.INC
    ;****************************************************************************************************
    ;
    ; Name........... NSRDLM for FAT12/FAT16/FAT32/NTFS
    ; File........... NSRDLM.INC
    ; Version........ 1.0.0
    ; Dependencies... x86
    ; Description.... Read disk loader file module
    ; Author......... 周文星 ( Zhou Wen Xing )
    ; CSDN Accounts.. SupermanKing
    ; Date........... Jan, 05nd 2011
    ; UpdateURL...... http://noah.rljy.com/
    ; QQ Codeing..... 44068232
    ; TEL............ +86.015677228819
    ; E-Mail......... humanhome@126.com
    ;
    ; Copyright (c) 2004-2011 by www.rljy.com
    ; LiuZhou city, China
    ;
    ;****************************************************************************************************
    %IF BOOT_MODE == FD_FAT12
    	%INCLUDE	"NSRDLM_FAT12.INC"
    %ELSE
    %IF BOOT_MODE == HD_FAT16
    	%INCLUDE	"NSRDLM_FAT16.INC"
    %ELSE
    %IF BOOT_MODE == HD_FAT32
    	%INCLUDE	"NSRDLM_FAT32.INC"
    %ELSE
    %IF BOOT_MODE == HD_NTFS
    	%INCLUDE	"NSRDLM_NTFS.INC"
    %ENDIF
    %ENDIF
    %ENDIF
    %ENDIF

    4、NS_VARIABLE.INC
    ;****************************************************************************************************
    ;
    ; Name........... NS_VARIABLE
    ; File........... NS_VARIABLE.INC
    ; Version........ 1.0.0
    ; Dependencies... x86
    ; Description.... Set static variable
    ; Author......... 周文星 ( Zhou Wen Xing )
    ; CSDN Accounts.. SupermanKing
    ; Date........... Jan, 05nd 2011
    ; UpdateURL...... http://noah.rljy.com/
    ; QQ Codeing..... 44068232
    ; TEL............ +86.015677228819
    ; E-Mail......... humanhome@126.com
    ;
    ; Copyright (c) 2004-2011 by www.rljy.com
    ; LiuZhou city, China
    ;
    ;****************************************************************************************************
    ;================================================================================================
    ; Public variable defining ( 全局变量定义 )
    ;================================================================================================
    READ_COUNT:		db	0			; 要读取的扇区数量
    BOOTFILE:		db	"KERNEL  BIN", 0x00
    TMPSTR:			db	"."
    SHOWSTR:		db	"CBCDEFGH", 0x00
    ;----------------------------------------------------------------------------------------------------
    ;※※※※※※※※※※※※※   全局变量定义  ( Public variable defining )   ※※※※※※※※※※※※※
    ;----------------------------------------------------------------------------------------------------
    FDT_TYPE:		db	0			; 文件类型,0为文件,1为目录,2为卷标
    FDT_ATTRIB:		db	0			; 文件属性
    FDT_SECADDR:		dw	0			; 文件数据起始扇区号
    FDT_SIZE:		dd	0			; 文件大小
    READ_SECTOR:		dw	0xFFFF			; 读磁盘的扇区号
    READ_TRACK:		db	0			; 读磁盘的磁道(柱面)号
    READ_HEADS:		db	0			; 读磁盘的磁头(面)号
    READ_SECSIZE:		dd	0			; 要读取的扇区数量

    5、NS_FUNCTION.INC 
    ;==================================================================================
    ; 字符串对比函数(NASM没有 cmps 函数)
    ; 输入参数:	AX	要对比的串地址
    ;		BX	要对比的串地址
    ;		CX	
    ; 返回参数:	ZF = 1 相等, ZF = 0 不想等
    ;==================================================================================
    ;----------------------------------------------------------------------------------------------------
    ; Function   Name: cmps
    ; Input Parameter: AX					- 要对比的串地址
    ;		 : BX					- 要对比的串地址
    ;		 : CX					- 要对比的字符串长度
    ; Return    Value: ZF					- 1为不想等,0为相等
    ; Description    : 字符串对比函数(NASM没有 cmps 函数)
    ;----------------------------------------------------------------------------------------------------
    cmps:
    	PUSH		SI				; 将 DS:SI 放入栈
    	PUSH		DI				; 将 ES:DI 放入栈
    	CLD
    	MOV		SI, AX
    	MOV		DI, BX
    	;========== 字符串自动长度判断对比过程 ==========
    cmps_loop:
    	LODSB						; ds:si -> al
    	CMP		AL, byte [ES:DI]		; 判断 al 与当前的 di 是否相等
    	JNZ		cmps_out			; al 与 di 不匹配结束判断过程
    	INC		DI				; di 地址偏移一个字节
    	DEC		CX				; CX--
    	CMP		CX, 0				; 判断 al 与当前的 di 是否相等
    	JZ		cmps_out			;
    	JMP		cmps_loop			; 继续判断下一个字符
    cmps_out:
    	POP		DI				; 将 DI 移出栈
    	POP		SI				; 将 SI 移出栈
    	RET
    
    ;----------------------------------------------------------------------------------------------------
    ; Function   Name: FindSectorFDT
    ; Input Parameter: AX					- 扇区数据地址
    ;		 : BX					- 要搜索的文件名地址
    ; Return    Value: ZF					- 0 为不想等,1为相等
    ;		 : AX					- 返回找到的文件数据起始扇区号
    ; Description    : 在FDT表中寻找指定文件名的文件并取得文件数据区的起始扇区号
    ;----------------------------------------------------------------------------------------------------
    FindSectorFDT:
    	PUSH		SI				; 将 DS:SI 放入栈
    	PUSH		DI				; 将 ES:DI 放入栈
    	PUSH		CX				; 将 CX 放入栈
    	MOV		SI, BX
    	MOV		DI, AX
    	MOV		CX, 16				; 设置循环搜索 16 个 FDT 表
    
    fsfdt_loop:
    	CMP		CX, 0
    	JZ		fsfdt_over			; 循环已结束
    	PUSH		CX				; 将 CX 放入栈
    	MOV		AX, DI
    	MOV		BX, SI
    	MOV		CX, 11
    	CALL		cmps				; 调用 cmps 函数对比字符串
    	POP		CX				; 将 CX 移出栈
    	JZ		fsfdt_ok			; 如果文件名相等结束循环并做载入处理
    	; 文件名不等的情况如下处理
    	ADD		DI, 32				; 让 ES:DI 向后偏移 32 个字节(到下一个 FDT 处)
    	DEC		CX				; CX--; 将 FDT 循环数减一
    	JMP		fsfdt_loop			; 继续循环
    
    fsfdt_ok:
    	ADD		DI, 26				; 移动 FDT 到数组族所在地址
    	MOV		AX, word [ES:DI]
    	ADD		AX, 31
    	MOV		word [FILE_ADDRESS], AX	
    
    fsfdt_over:
    	POP		CX				; 将 CX 移出栈
    	POP		DI				; 将 DI 移出栈
    	POP		SI				; 将 SI 移出栈
    	RET
    
    ;----------------------------------------------------------------------------------------------------
    ; 16 位实时模式下直接通过调用 BIOS 中断 13h 实现磁盘读写操作
    ;----------------------------------------------------------------------------------------------------
    ;----------------------------------------------------------------------------------------------------
    ; Function   Name: RDSector
    ; Input Parameter: AX					- 读取磁盘扇区的缓冲区地址
    ;		 : CL					- 要读磁盘扇区的起始扇号
    ;		 : CH					- 要读磁盘扇区的磁道(柱面)号
    ;		 : DL					- 要读磁盘扇区的驱动器号( 00H-7FH 表示软驱 00h是第一个软驱,01h是第二个软驱..., 80H-0FFH 表示硬盘 )
    ;		 : DH					- 要读磁盘扇区的磁头(面)号
    ; Return    Value: AX					- 将读到的扇区数据返回到 AX 指定的缓冲区中
    ; Description    : Read Disk Sector.( 读取磁盘扇区, )
    ;----------------------------------------------------------------------------------------------------
    RDSector:
    	; 磁盘复位
    	;XOR		AH, 00h				; 通过功能 00H 设置为磁盘系统复位功能
    	;XOR		DL, BOOT_DRV			; 设置要处理的驱动器号( 00H-7FH 表示软驱 00h是第一个软驱,01h是第二个软驱..., 80H-0FFH 表示硬盘 )
    	;INT		13h				; 调用 BIOS 中断开始处理
    	; 开始读取磁盘扇区
    	PUSH		BX				; 将 es:bx 放入栈
    	MOV		BX, AX				; 设置缓冲区的地址
    	PUSH		AX				; 将 AX 放入栈
    	MOV		AH, 02h				; 通过功能 02H 设置为读扇区功能
    	MOV		AL, 1				; 设置要读的扇区数
    	INT		13h				; 调用 BIOS 中断开始处理
    	POP		AX				; 将 AX 移出栈
    	POP		BX				; 将 es:bx 移出栈
    	RET
    
    ;----------------------------------------------------------------------------------------------------
    ; Function   Name: LoaderFile
    ; Input Parameter: AX					- 要搜索的文件名串地址
    ;		 : BL					- 要搜索的磁盘驱动器号
    ;		 ; DX					- 指定加载到内存的内存地址
    ; Return    Value: AX					- 0 为加载成功,非零表示失败
    ; Description    : Search Disk File.( 搜索指定磁盘文件 )
    ;----------------------------------------------------------------------------------------------------
    ; FDT 表起始位置计算公式:
    ; FDT 起始扇区号 = BPB_FATSz16(FAT扇区数) * BPB_NumFATs(FAT表数) + 1(引导扇区)
    ; FDT 表扇区总数:
    ; FDT 表扇区总数 = BPB_RootEntCnt(最大文件数) / 32(FDT表大小)
    LoaderFile:
    	; 先搜索 FDT 表,找到数据起始地址后,再根据 FAT 表读数据
    	; ---------- 搜索 FDT 表 ----------
    	PUSH		DI				; 将 ES:DI 放入栈
    	PUSH		SI				; 将 DS:SI 放入栈
    	PUSH		CX				; 将 CX 放入栈
    	MOV		SI, AX
    	XOR		CX, CX				; 将计数器 CX 清零
    	MOV		CL, byte [FDT_BEGINSEC]		; 初始化计数器为 FDT 开始扇区号
    
    	; 开始循环 FDT 表寻找指定文件的过程
    FindFile_NextSector:
    	MOV		AL, byte [FDT_SECCOUNT]		; 设置 AX 寄存器为 FDT 表扇区总数
    	ADD		AL, byte [FDT_BEGINSEC]		; 然后在 FDT 表扇区总数加上 FDT 开始扇区号
    	CMP		CX, AX				; 判断 CX 与 AX 是否相等,如果两数相等,表示超出边界,
    							; ZF 会设置为 1
    	JZ		FindFile_Over			; 根据 ZF 状态决定是否跳转到 FindFile_Over 位置
    
    	; ---------- 读 FDT 表所在扇区数据到 LOADERADDR 的内存地址处  ----------
    	MOV		AX, CX				; 先将 当前计数器中的扇区号传递到 AX 作为参数
    	CALL		GetPDI				; 调用 GetPDI 函数转换逻辑扇区号为物理扇区号
    	; ---------- 开始读取指定物理扇区的整个扇区内容到 LOADERADDR 的内存地址处 ----------
    	MOV		AX, LOADERADDR			; 设置数据缓冲区到 LOADERADDR 地址上
    	MOV		DL, BOOT_DRV			; 设置设备号为启动盘的设备号
    	CALL		RDSector			; 调用 RDSector 函数开始读取扇区内容
    	INC		CX				; CX++(自动添加预读取的 FDT 逻辑扇区号码)
    	; ---------- 开始在读取的扇区数据循环读取每一个 FDT 表数据,同时判断是否有指定的文件存在 ----------
    	MOV		AX, LOADERADDR			; 设置比对用的数据源地址
    	MOV		BX, SI				; 设置要对比的文件名地址(因为上面先把AX参数存入了 SI 里)
    	CALL		FindSectorFDT			; 开始搜索扇区中的 FDT 信息是否存在指定文件信息
    	JNZ		FindFile_NextSector		; 判断 FindSectorFDT 返回参数是否找到了指定文件,如果
    							; 没有找到,就继续循环读取下一个扇区进行查找
    	; 开始根据 FAT 数据表加载数据
    FindFile_Read:
    	XOR		CX, CX				; CX 计数器清零
    	INC		CX				; CX+1
    	; 读取一个扇区的 FAT 内容
    	MOV		AX, CX				; 先将 当前计数器中的扇区号传递到 AX 作为参数
    	CALL		GetPDI				; 调用 GetPDI 函数转换逻辑扇区号为物理扇区号
    	MOV		AX, LOADERADDR			; 设置数据缓冲区到 LOADERADDR 地址上
    	MOV		DL, BOOT_DRV			; 设置设备号为启动盘的设备号
    	CALL		RDSector			; 调用 RDSector 函数开始读取扇区内容
    	MOV		DI, LOADERADDR
    FindFile_FAT_Loop:
    	MOV		AX, DI
    	ROR		AX, 8				; AX>>8 向右偏移 8 个二进制位
    	AND		AX, 0xFFF			; 取后 12 个二进制位
    	CMP		AX, FILE_ADDRESS		; 对比 数据地址是否与找到的数据地址相同
    	JZ		FindFile_READ_FAT		; 找到FAT数据开始处
    	; 没有找到与 FDT 对应的 FAT 地址处
    	INC		DI				; 让 ES:DI 向后偏移 1 个字节(到下一个 FDT 处)
    	INC		CX				; CX 计数器加一
    	JMP		FindFile_FAT_Loop
    FindFile_READ_FAT:
    	XOR		AX, AX				; AX 清零,表示成功
    FindFile_Over:
    	POP		CX				; 讲影响了的 CX 寄存器出栈(恢复入栈时的值)
    	POP		SI				; 讲影响了的 SI 寄存器出栈(恢复入栈时的值)
    	POP		DI				; 讲影响了的 DI 寄存器出栈(恢复入栈时的值)
    	RET
    
    ;==================================================================================
    ; 调用 BIOS 中断 int 10h 的 13H 功能  在 Teletype 模式下显示字符串
    ;==================================================================================
    ;----------------------------------------------------------------------------------------------------
    ; Function   Name: Print
    ; Input Parameter: AX					- 要输出字符串的地址
    ;		 : CX					- 要输出字符串的字节长度
    ; Description    : Print string to screen.( 输出字符串到屏幕 )
    ;----------------------------------------------------------------------------------------------------
    Print:
    	PUSH		BP
    	PUSH		BX
    	MOV		BP, AX
    	PUSH		AX
    
    	; 设置功能号 AH = 13		同时设置 AL = 01h(配合 BL 参数设置属性)
    	;						 AL = 显示输出方式
    	;						 0	字符串中只含显示字符,其显示属性在BL中。显示后,光标位置不变
    	;						 1	字符串中只含显示字符,其显示属性在BL中。显示后,光标位置改变
    	;						 2	字符串中含显示字符和显示属性。显示后,光标位置不变
    	;						 3	字符串中含显示字符和显示属性。显示后,光标位置改变
    	MOV		AX, 1301h			; AH = 13,  AL = 01h
    	MOV		BX, 0007h			; 页号为0(BH = 0) 黑底白字(BL = 07h,高亮)
    	INC		DL				; 行号
    	INT		10h				; 10h 号中断
    
    	POP		AX
    	POP		BX
    	POP		BP
    	RET
    ;----------------------------------------------------------------------------------------------------
    ; Function   Name: GetPDI
    ; Input Parameter: AX					- 要换算的逻辑扇区号
    ; Return    Value: CL					- 磁盘扇区号
    ;		 : CH					- 磁盘磁道(柱面)号
    ;		 : DL					- 驱动器号
    ;		 : DH					- 磁盘磁头(面)号
    ; Description    : 将逻辑扇区号换算成物理扇区信息
    ;----------------------------------------------------------------------------------------------------
    ; 换算物理磁头、磁道、扇区的方法如下:
    ; 扇区 = (逻辑扇区号 MOD 每道扇区数) + 1
    ; 磁道 = (逻辑扇区号 / 每道扇区数) / 磁头数
    ; 磁头 = (逻辑扇区号 / 每道扇区数) MOD 磁头数
    ;----------------------------------------------------------------------------------------------------
    GetPDI:
    	PUSH		BX				; 将 BX 放入栈
    	;---------- 计算磁头和磁道号 ----------
    	;公式:LBA(逻辑扇区号-1) / BPB_SecPerTrk(每磁道扇区数)
    	MOV		BX, word [BPB_SecPerTrk]	; 设置被除数
    	DIV		BL				; 开始除法运算:逻辑扇区号 / BPB_SecPerTrk
    	INC		AH				; 得到物理扇区号
    	MOV		CL, AH				; 将余数设置到 CL 寄存器
    	XOR		AH, AH				; 清楚余数结果,只要 AL 中的整除结果
    	MOV		BX, word [BPB_NumHeads]		; 设置磁头数为被除数
    	DIV		BL				; 开始除法运算:(LBA / BPB_SecPerTrk) MOD BPB_NumHead
    	MOV		DH, AH				; 得到磁头号,将余数设置到 DH 寄存器
    	MOV		CH, AL				; 得到磁道号,将余数设置到 CH 寄存器
    	POP		BX				; 将 BX 移出栈,同时恢复 BX 原始的内容
    	RET

    6、NSRDLM_FAT12.INC
    ;****************************************************************************************************
    ;
    ; Name........... NSRDLM for FAT12
    ; File........... NSRDLM_FAT12.INC
    ; Version........ 1.0.0
    ; Dependencies... x86
    ; Description.... Read disk loader file module for FAT12
    ; Author......... 周文星 ( Zhou Wen Xing )
    ; CSDN Accounts.. SupermanKing
    ; Date........... Jan, 05nd 2011
    ; UpdateURL...... http://noah.rljy.com/
    ; QQ Codeing..... 44068232
    ; TEL............ +86.015677228819
    ; E-Mail......... humanhome@126.com
    ;
    ; Copyright (c) 2004-2011 by www.rljy.com
    ; LiuZhou city, China
    ;
    ;****************************************************************************************************
    ;----------------------------------------------------------------------------------------------------
    ;※※※※※※※※※※※※※※※※※※    FAT12 分区表结构说明    ※※※※※※※※※※※※※※※※※※
    ;----------------------------------------------------------------------------------------------------
    ;┌───────┬────────────┬────────────┬───────────────┬──────┐
    ;│ (1扇区)MBR表 │(BPB_FATSz16扇区)FAT表1 │(BPB_FATSz16扇区)FAT表2 │(BPB_RootEntCnt/32)扇区)FTD表 │FAT12 数据区│
    ;└───────┴────────────┴────────────┴───────────────┴──────┘
    ; [FAT 表数据区格式]
    ;┌────┬──────┬───────────────┐
    ;│   0F   │   FF FF    │ 12个二进制位的数据扇区地址表 │
    ;└────┴──────┴───────────────┘
    ;  存储介质   系统固定值      详细参考 FAT 数据表说明
    ;
    ; ------------------------------ 详细参考 FAT 数据表说明 ------------------------------
    ; 000			- 表示此簇未用
    ; FF0 - FF7		- 表示此簇为坏,不可用
    ; FF8 - FFF		- 表示该簇为文件的最后一簇
    ; 其它值表示文件下一簇的簇号
    ; 簇的逻辑位置为 簇号+31
    ; 这个31是由 保留扇区数 + 隐藏扇区数 + FAT数×每个FAT所占扇区数 + FDT所占扇区数 - 2
    ; 公式为:1 + 0 + 2*18 + 14 - 2
    ; 二进制位合成为后一个字节的低 4 位累加到第一个字节的高8位之上
    ; 如:数据为 05 60 00 表示连续的两个簇
    ; 第一个簇位置为:
    ; 0x60		0x05
    ; 01100000	00000101	将数据换算成二进制
    ; 0110 0000	00000101	划分出12个二进制位作为要取得的值
    ; 0110		000000000101	演变成这样的数据
    ; 取低 12 位,取得 5 这个值
    ; 将 5+31 = 36 ,表示下一个簇的数据在 36 簇上
    ; 同理的,再下一的族的数据这样计算
    ; 0x00		0x60
    ; 00000000	01100000	将数据换算成二进制
    ; 00000000	0110 0000	划分出12个二进制位作为要取得的值
    ; 000000000110	0000		演变成这样的数据
    ; 取高12位,取得 6 这个值
    ; 将 6+31 = 37 ,表示下一个簇的数据在 37 簇上
    ;----------------------------------------------------------------------------------------------------
    ; 换算物理磁头、磁道、扇区的方法如下:
    ; LBA = 逻辑扇区号 - 1
    ; 扇区 = (LBA MOD 每道扇区数) + 1
    ; 磁道 = (LBA / 每道扇区数) / 磁头数
    ; 磁头 = (LBA / 每道扇区数) MOD 磁头数
    ;====================================================================================================
    ; -----------------------------------        数 据 表 范 例       -----------------------------------
    
    ; 0F FF FF 11 12 22 33 3F FF ...
    ; 0F FF FF	.................. 为 FAT12 固定格式
    ; 11 1		.................. 为 12 个二进制位的数据扇区数
    ; 2 22		.................. 为下一个数据扇区数
    ; 33 3		.................. 为下一个数据扇区数
    ; F FF		.................. 为最后一簇
    ;----------------------------------------------------------------------------------------------------
    ; [FDT 表数据区格式]
    ;┌────┬────┬───┬───────┬────────┬────────┬──────────┬────┐
    ;│ 文件名 │ 扩展名 │ 属性 │ 系统保留段落 │最后一次写入时间│最后一次写入日期│此条目对应的开始族号│文件大小│
    ;├────┼────┼───┼───────┼────────┼────────┼──────────┼────┤
    ;│ 8 字节 │ 3 字节 │1 字节│    10 字节   │     2 字节     │      2 字节    │       2 字节       │ 4 字节 │
    ;└────┴────┴───┴───────┴────────┴────────┴──────────┴────┘
    ;
    ; [系统保留段落数据区格式]
    ;┌─────┬─────────┬──────┬──────┬────────┬─────────┐
    ;│ 系统保留 │创建时间的10毫秒位│文件创建时间│文件创建日期│文件最后访问日期│文件起始簇的高16位│
    ;├─────┼─────────┼──────┼──────┼────────┼─────────┤
    ;│  1 字节  │      1 字节      │   2 字节   │   2 字节   │     2 字节     │      2 字节      │
    ;└─────┴─────────┴──────┴──────┴────────┴─────────┘
    ;
    ;----------------------------------------------------------------------------------------------------
    ; [时间格式]
    ;----------------------------------------------------------------------------------------------------
    ; 换算公式:小时*2048+分钟*32+秒/2
    ; 二进制位说明:0-4 bit		2秒为单位
    ;		5-10 bit	为分钟
    ;		11-15 bit	为小时
    ; 转换时间数据范例:
    ; ----- ------- -----
    ;   时	  分	 秒
    ; ----- ------- -----
    ; 05	24	32			未转换的时间信息
    ; 05	24	16			已转换的时间信息
    ; 00101	011000	10000			将时间分析成二进制
    ; 0010101100010000			组合所有二进制位
    ; 2B 10					转换二进制为16进制( 得到以下结果 )
    ;
    ;----------------------------------------------------------------------------------------------------
    ; [日期格式]
    ;----------------------------------------------------------------------------------------------------
    ; 换算公式:(年份-1980)*512+月份*32+日
    ; 二进制位说明:0-4 bit		为日期
    ;		5-8 bit		为月份
    ;		9-15 bit	为年份 范围 0-127 表示 1980-2107年
    ; 转换日期数据范例:
    ; ------------- ------- ----
    ;   年		  月	 日
    ; ------------- ------- ----
    ; 2011		10	11		未转换的日期信息
    ; 31		10	11		已转换的日期信息
    ; 0011111	1010	01011		将日期分析成二进制
    ; 0011111101001011			组合所有二进制位
    ; 3F 4B					转换二进制为16进制( 得到以下结果 )
    ;----------------------------------------------------------------------------------------------------
    ;※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
    ;----------------------------------------------------------------------------------------------------
    
    
    ;====================================================================================================
    ; Public variable defining ( 全局变量定义 )
    ;====================================================================================================
    FDT_SECCOUNT		db	0			; FDT 表扇区总数
    FDT_SECSIZE		db	0			; FDT 表每扇区数量
    FDT_BEGINSEC		db	0			; FDT 开始扇区号
    FILE_ADDRESS		dw	0
    
    
    ; 尝试输出文件名数据
    ; Input Parameter: AX					- 读取磁盘扇区的缓冲区地址
    ;		 : CL					- 要读磁盘扇区的起始扇号
    ;		 : CH					- 要读磁盘扇区的磁道(柱面)号
    ;		 : DL					- 要读磁盘扇区的驱动器号( 00H-7FH 表示软驱 00h是第一个软驱,01h是第二个软驱..., 80H-0FFH 表示硬盘 )
    ;		 : DH					- 要读磁盘扇区的磁头(面)号
    ; LBA = 逻辑扇区号 - 1
    ; 扇区 = (LBA MOD 每道扇区数) + 1
    ; 磁道 = (LBA / 每道扇区数) / 磁头数
    ; 磁头 = (LBA / 每道扇区数) MOD 磁头数
    
    ; ---------- 计算 FDT 开始扇区号 ----------
    ; 公式:FDT_BEGINSEC(FDT 开始扇区号) = BPB_FATSz16(FAT扇区数) * BPB_NumFATs(FAT表数) + 1(引导扇区)
    	XOR		AX, AX
    	XOR		BX, BX
    	MOV		AL, byte [BPB_FATSz16]		; 设置乘数为 BPB_FATSz16(FAT扇区数)
    	MOV		BL, byte [BPB_NumFATs]
    	MUL		BL				; 乘法运算:BPB_FATSz16(FAT扇区数) * BPB_NumFATs(FAT表数)
    	ADD		AX, 1				; 加法运算:相乘结果 + 1(引导扇区)
    	MOV		byte [FDT_BEGINSEC], AL		; 将运算结果放入 FDT_BEGINSEC 变量
    ; ---------- 计算 FDT 每扇区数 ----------
    ; 公式:FDT_SECSIZE(FDT 表每扇区数量) = BPB_BytsPerSec(每扇区字节数) / 32(FDT 表的字节大小)
    	MOV		AX, word [BPB_BytsPerSec]	; 设置 16 位的除数
    	MOV		BX, 32				; 设置被除数 (32 为 FDT 表的字节大小)
    	DIV		BL				; 开始除法运算: BPB_RootEntCnt(每扇区字节数) / 32(FDT表大小)
    	MOV		byte [FDT_SECSIZE], AL		; 将运算结果放入 FDT_SECSIZE 变量
    
    ; ---------- 计算 FDT 扇区总数 ----------
    ; 公式:FDT_SECCOUNT(FDT 表扇区总数) = BPB_RootEntCnt(最大文件数) / FDT_SECSIZE(FDT 每扇区数)
    	MOV		AX, word [BPB_RootEntCnt]	; 设置16位的除数
    	XOR		BX, BX				; BX 清零
    	MOV		BL, byte [FDT_SECSIZE]		; 设置被除数
    	DIV		BL				; 开始除法运算: BPB_RootEntCnt(最大文件数) / FDT_SECSIZE(FDT 表每扇区数量)
    	MOV		byte [FDT_SECCOUNT], AL		; 将运算结果放入 FDT_SECCOUNT 变量
    
    ; ---------- 设置要读取的扇区信息 ----------
    
    
    	;MOV		AX, ReadFDT
    	;MOV		CX, 3
    
    	;XOR		AX, AX
    	;MOV		AL, byte [FDT_BEGINSEC]
    	;MOV		BX, SHOWSTR
    	;CALL		IntToStr
    
    	;MOV		AL, SHOWSTR
    	;CALL		Print
    
    	;PUSH		DI				; 将 DI 放入栈
    	;MOV		DI, SHOWSTR
    	;MOV		AX, word [FILE_ADDRESS]
    	;MOV		byte [ES:DI], AH
    	;INC		DI
    	;MOV		byte [ES:DI], AL
    	;POP		DI
    
    	; 先查询 FDT 表文件是否存在,如果存在,则取得FDT表中的文件数据起始扇区号到 FILE_ADDRESS 变量里
    	MOV		AX, BOOTFILE			; 设置要查询的文件名缓冲区地址
    	MOV		DX, LOADERADDR
    	CALL		LoaderFile
    
    	MOV		AX, word [FILE_ADDRESS]		; 设置 AX 寄存器为读到的文件起始扇区数
    	CALL		GetPDI				; 将逻辑扇区号换算成物理扇区信息
    	MOV		AX, LOADERADDR			; 设置要读取磁盘扇区的缓冲区地址
    	MOV		DL, BOOT_DRV			; 设置要要读磁盘扇区的驱动器
    	CALL		RDSector			; 开始读取指定磁盘扇区内容
    
    	;MOV		AX, LOADERADDR			; 设置要显示数据的缓冲区地址
    	;MOV		CX, 512				; 设置要显示数据的缓冲区大小
    	;CALL		BuffToHexStr			; 开始以十六进制字符形式显示指定缓冲区的数据


  • 相关阅读:
    IDEA创建Javaweb工程
    配置Info.plist (设置状态栏样式、自定义定位时系统弹出的提示语、配置3DTouch应用快捷菜单)
    关于IQKeyBoardManager挤出导航栏的解决方案
    iOS应用内跳转系统设置相关界面的方法
    解决xcode打开时loading假死的问题
    iOS图片按比例显示
    iOS开发-UITableView顶部图片下拉放大
    自定义按钮 图片+文字
    iOS开发-NSOperation与GCD区别
    iOS开发-UINavigationBar透明设置
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/2992087.html
Copyright © 2020-2023  润新知