⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat32引导扇区代码.shtm.htm

📁 支持FAT32和NTFS的引导扇区源码
💻 HTM
📖 第 1 页 / 共 5 页
字号:
  </tr>
</tbody></table>
</td>
              </tr>
              <tr>
                <td width="10"></td>
                <td><span id="ArticleContent1_ArticleContent1_lblContent"><p>;====================================================================<br>; <br>; FlyingDragon OS Boot Sector FOR FAT32<br>;<br>; Author: Jack<br>; V0.01 2005-07-23 17:39<br>; V0.02&nbsp;2005-08-07 09:29<br>; <br>; Build : nasm -f bin FAT32.ASM -oFAT32.BIN&nbsp;<br>; &nbsp;<br>;====================================================================================<br>; <br>; BIOS在启动中的角色:<br>; &nbsp;(1) BIOS装载引导驱动器上的0扇区(CHS = 0:0:1)内容到内存线性地址7C00H处;<br>; &nbsp;(2) BIOS检查所装载的扇区是否有启动标记(510、511字节分别为55H和AAH); <br>; &nbsp;(3) CPU寄存器DL被设置为分配给引导驱动器的驱动器号,00H为软驱A,80H为硬盘C;<br>; &nbsp;(4) BIOS跳转到其装载的扇区中的代码(即7C00H处),将控制权转交给引导代码。<br>; <br>; 引导代码应该初始化以下寄存器:<br>; &nbsp;(1) DS:某些BIOS设置其值为0,某些设置其为40H,它应该被设置为(7C00H-BOOT_ORG)/16;<br>; &nbsp;&nbsp;其中,BOOT_ORG为引导代码的ORG值,该值通常为7C00H(这意味着DS应设置为0);<br>; &nbsp;(2) SS和SP(堆栈):这两个寄存器的初始值依赖于BIOS;<br>; &nbsp;(3) CS个IP(通过JMP指令):大多数的BIOS进入启动代码的地址为0000:7C00H,但是某些<br>; &nbsp;&nbsp;BIOS却跳转到07C0:0000H。由于短跳转和条件跳转是IP相关的,因此如果没有使用<br>;&nbsp;&nbsp;远跳转或者绝对跳转,则不需要重置CS和IP;然而,DS仍旧必须是正确的值。<br>; <br>;=====================================================================================<br>; <br>; 常规内存( 0000 0000H - 000F FFFFH,即0-1MB )在系统启动时的使用情况<br>; <br>;=====================================================================================<br>; <br>; &nbsp;&nbsp;---------------------------------<br>; &nbsp;&nbsp;|&nbsp;0000 0000 - 0000 03FF&nbsp;&nbsp; &nbsp;|&nbsp;1024B&nbsp; &nbsp;IDT&nbsp; read only<br>; &nbsp;&nbsp;|-------------------------------|<br>; &nbsp;&nbsp;|&nbsp;0000 0400 - 0000 04FF&nbsp;&nbsp;|&nbsp;256B &nbsp;BIOS Data Area , read only&nbsp;<br>; &nbsp;&nbsp;|-------------------------------|<br>; &nbsp;&nbsp;|&nbsp;0000 0500 - 0000 7BFF&nbsp; &nbsp;|*&nbsp;30464B&nbsp;Free Memory , read/write &nbsp;(29.75KB) <br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>; &nbsp;&nbsp;|&nbsp;0000 7C00 - 0000 7DFF&nbsp;&nbsp; &nbsp;|&nbsp;512B&nbsp;Boot Sector , read/write&nbsp;<br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>; &nbsp;&nbsp;|&nbsp;0000 7E00 - 0000 7FFF&nbsp;&nbsp;|&nbsp;512B&nbsp;&nbsp;&nbsp; Free Memory , read /write<br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>; &nbsp;&nbsp;|&nbsp;0000 8000 - 0009 FBFF&nbsp; &nbsp;|&nbsp;607KB&nbsp;Free Memory , read / write( 32K - 639KB ) <br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>;
&nbsp;&nbsp;|&nbsp;0009 FC00 - 0009 FFFF&nbsp;&nbsp;
&nbsp;|**&nbsp;1KB&nbsp;&nbsp;EBDA extended BIOS data
area&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>; &nbsp;&nbsp;|&nbsp;000A 0000 - 000A FFFF&nbsp;&nbsp;|&nbsp;64KB&nbsp;Video Memory<br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>; &nbsp;&nbsp;|&nbsp;000B 0000 - 000B 7FFF&nbsp; &nbsp;|&nbsp;32KB&nbsp;Mono Video Text Memory <br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>; &nbsp;&nbsp;|&nbsp;000B 8000 - 000B FFFF&nbsp;&nbsp; &nbsp;|&nbsp;32KB&nbsp;Color Video Text Memory<br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>; &nbsp;&nbsp;|&nbsp;000C 0000 - 000C 7FFF&nbsp;&nbsp;|&nbsp;32KB&nbsp;Video BIOS , read only<br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>; &nbsp;&nbsp;|&nbsp;000C 8000 - 000E FFFF&nbsp; &nbsp;|&nbsp;160KB&nbsp;Adapter ROM,read only<br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>; &nbsp;&nbsp;|&nbsp;000F 0000 - 000F FFFF&nbsp;&nbsp; &nbsp;|&nbsp;64KB&nbsp;System BIOS, read only<br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>; &nbsp;&nbsp;|&nbsp;0010 0000 - 0010 FFEF&nbsp;&nbsp;|***64KB-16&nbsp;High Memory Area,read/write&nbsp; ( 1MB开始处 )<br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>; &nbsp;&nbsp;|&nbsp;0010 FFF0 - &nbsp;&nbsp;&nbsp; &nbsp;|&nbsp;&nbsp;&nbsp;Free Extended Memory, read/write&nbsp;<br>; &nbsp;&nbsp;|------------------------------&nbsp;|<br>; <br>; &nbsp;*&nbsp;空闲内存实际并非从 0000 0500处开始,BIOS数据区实际上会利用从0000 0500开始的少量字节,例如<br>; &nbsp;&nbsp;00000500处保存的是打印屏幕状态,当按下打印屏幕(PrintScreen)键时,低级键盘BIOS初始化打印屏<br>; &nbsp;&nbsp;幕功能,键盘BIOS触发中断5打印屏幕处理程序。正因为BIOS数据区越过了256B的界限,因此DOS实际<br>; &nbsp;&nbsp;上是从0000 0522开始装载的。为保险起见,可从0000 0600开始利用空闲内存。(1.5K - 31K 29.5KB)<br>; <br>; **&nbsp;有些机器上没有这段BIOS扩展数据区。<br>; <br>; ***&nbsp;如果没有使用扩展高端内存区域程序(例如Emm386.exe),则从0010 0000 (1MB )开始的内存都是可用的。<br>; <br>; <br>;=====================================================================================<br>; </p><p>BITS &nbsp;&nbsp;16&nbsp;&nbsp;&nbsp;; 生成16位代码而不是32位代码<br>SECTION&nbsp;&nbsp;.TEXT &nbsp;&nbsp;; 代码段<br>ORG&nbsp;&nbsp;&nbsp;7C00H&nbsp;&nbsp;; 指定程序被装入内存的起始位置</p><p>;====================================================================<br>; <br>; 宏和常量定义<br>; <br>;====================================================================<br>? &nbsp;&nbsp;&nbsp;&nbsp;EQU &nbsp;0&nbsp;&nbsp;; NASM不支持DW ?这样的语法,可以使用这样的定义<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 模拟,以使代码的可读性更强<br>DATA_BUF_SEG&nbsp;EQU&nbsp;&nbsp;0200H&nbsp;; 用于读取根目录或文件内容的缓冲区(8K) 段地址<br>DATA_BUF_OFF&nbsp;EQU&nbsp;&nbsp;2000H<br>STACK_ADDR&nbsp;&nbsp;EQU&nbsp;&nbsp;7BD0H&nbsp;; 堆栈栈顶(注意:堆栈大小约为20K)&nbsp;<br>OSLOADER_ADDR&nbsp;EQU&nbsp;&nbsp;8000H&nbsp;; FDOSLDR.BIN放入内存中的起始位置,这就意味着<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 装载程序及相关资源的尺寸不能超过608K<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 8000H - A000H (32K - 640K )<br>OSLOADER_SEG&nbsp;EQU&nbsp;&nbsp;0800H&nbsp;; 起始段地址&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>SECOND_SECTOR&nbsp;EQU&nbsp;&nbsp;03H&nbsp;&nbsp;; 第二个引导扇区的扇区号(第四个扇区)<br>SECOND_ADDR&nbsp;&nbsp;EQU&nbsp;&nbsp;7E00H&nbsp;; 第二个引导扇区的装载位置</p><p>;====================================================================<br>; 用堆栈保存若干中间变量( SS = 0 BP = 7C00H )<br>;====================================================================<br>FAT_START_SECTOR&nbsp;EQU&nbsp;&nbsp;4&nbsp;&nbsp;; FAT表的起始扇区号&nbsp;&nbsp;DWORD<br>ROOT_START_SECTOR&nbsp;EQU&nbsp;&nbsp;8&nbsp;&nbsp;; 根目录的起始扇区号&nbsp;DWORD<br>DATA_START_SECTOR&nbsp;EQU&nbsp;&nbsp;12&nbsp;&nbsp;; 数据区起始扇区号&nbsp;&nbsp;DWORD<br>FAT_ENTRY_SECTORS&nbsp;EQU&nbsp;&nbsp;14&nbsp;&nbsp;; FAT表所占的扇区数&nbsp;&nbsp;WORD<br>ROOT_ENTRY_SECTORS&nbsp;EQU&nbsp;&nbsp;16&nbsp;&nbsp;; 根目录所占的扇区数&nbsp;WORD<br>DIR_PER_SECTOR&nbsp;&nbsp;EQU&nbsp;&nbsp;17&nbsp;&nbsp;; 每个扇区所容纳的目录&nbsp;BYTE<br>DISK_EXT_SUPPORT&nbsp;EQU&nbsp;&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp; ; 磁盘是否支持扩展BIOS&nbsp;BYTE<br>CURRENT_CLUSTER&nbsp;&nbsp;EQU&nbsp;&nbsp;40&nbsp;&nbsp;; 当前正在处理的簇号&nbsp;DWORD</p><p><br>;====================================================================&nbsp;&nbsp;<br>; 扩展磁盘服务所使用的地址包<br>;====================================================================<br>DAP_SECTOR_HIGH&nbsp;&nbsp;EQU&nbsp;&nbsp;24&nbsp;&nbsp;; 起始扇区号的高32位 ( 每次调用需要重置 )&nbsp;DWORD<br>DAP_SECTOR_LOW&nbsp;&nbsp;EQU&nbsp;&nbsp;28&nbsp;&nbsp;; 起始扇区号的低32位 ( 每次调用需要重置 )&nbsp;DWORD<br>DAP_BUFFER_SEG&nbsp;&nbsp;EQU&nbsp;&nbsp;30&nbsp;&nbsp;; 缓冲区段地址&nbsp;&nbsp; ( 每次调用需要重置 )&nbsp;WORD<br>DAP_BUFFER_OFF&nbsp;&nbsp;EQU&nbsp;&nbsp;32&nbsp;&nbsp;; 缓冲区偏移&nbsp;&nbsp; ( 每次调用需要重置 )&nbsp;WORD&nbsp;&nbsp;<br>DAP_RESERVED2&nbsp;&nbsp;EQU&nbsp;&nbsp;33&nbsp;&nbsp;; 保留字节<br>DAP_READ_SECTORS&nbsp;EQU&nbsp;&nbsp;34&nbsp;&nbsp;; 要处理的扇区数(1 - 127 )<br>DAP_RESERVED1&nbsp;&nbsp;EQU&nbsp;&nbsp;35&nbsp;&nbsp;; 保留字节<br>DAP_PACKET_SIZE&nbsp;&nbsp;EQU&nbsp;&nbsp;36&nbsp;&nbsp;; 包的大小为16字节</p><p>;====================================================================<br>; <br>; 目录项结构(每个结构为32字节)<br>; <br>;====================================================================<br>OFF_DIR_NAME&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;0&nbsp;&nbsp;; 目录项的偏移&nbsp;&nbsp;BYTE[11]<br>OFF_DIR_ATTRIBUTE&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;11&nbsp;&nbsp;; 目录属性&nbsp;&nbsp;&nbsp;BYTE<br>OFF_NT_RESERVED&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;12&nbsp;&nbsp;; 保留属性&nbsp;&nbsp;&nbsp;BYTE<br>OFF_CREATE_TIME_HUNDREDTH&nbsp;EQU&nbsp;&nbsp;13&nbsp;&nbsp;; 创建时间&nbsp;&nbsp;&nbsp;BYTE<br>OFF_CREATE_TIME&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;14&nbsp;&nbsp;; 创建时间&nbsp;&nbsp;&nbsp;WORD<br>OFF_CREATE_DATE&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;16&nbsp;&nbsp;; 创建时间&nbsp;&nbsp;&nbsp;WORD<br>OFF_LAST_ACCESS_DATE&nbsp;&nbsp;EQU&nbsp;&nbsp;18&nbsp;&nbsp;; 上次访问时间&nbsp;&nbsp;WORD<br>OFF_START_CLUSTER_HIGH&nbsp;&nbsp;EQU&nbsp;&nbsp;20&nbsp;&nbsp;; 起始簇号高位&nbsp;&nbsp;WORD<br>OFF_LAST_UPDATE_TIME&nbsp;&nbsp;EQU&nbsp;&nbsp;22&nbsp;&nbsp;; 上次更新时间&nbsp;&nbsp;WORD<br>OFF_LAST_UPDATE_DATE&nbsp;&nbsp;EQU&nbsp;&nbsp;24&nbsp;&nbsp;; 上次更新时间&nbsp;&nbsp;WORD<br>OFF_START_CLUSTER_LOW&nbsp;&nbsp;EQU&nbsp;&nbsp;26&nbsp;&nbsp;; 起始簇号低位&nbsp;&nbsp;WORD<br>OFF_FILE_SIZE&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;28&nbsp;&nbsp;; 文件尺寸&nbsp;&nbsp;&nbsp;DWORD</p><p>; 相关常量<br>DIR_NAME_DELETED&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;0E5H&nbsp;; 该项已经被删除<br>DIR_NAME_FREE&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;00H&nbsp;&nbsp;; 该项是空闲的(其后也是空闲的)<br>DIR_NAME_DOT&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;2EH&nbsp;&nbsp;; 特殊目录 . 或 ..<br>DIR_NAME_SPACE&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;20H&nbsp;&nbsp;; 不允许的字符<br>DIR_ENTRY_SIZE&nbsp;&nbsp;&nbsp;&nbsp;EQU &nbsp;32&nbsp;&nbsp;; 每个目录项的尺寸,其结构如上所示&nbsp;</p><p>;文件属性<br>DIR_ATTR_READONLY&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;01H&nbsp;&nbsp;; 只读文件<br>DIR_ATTR_HIDDEN&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;02H&nbsp;&nbsp;; 隐藏文件<br>DIR_ATTR_SYSTEM&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;04H&nbsp;&nbsp;; 系统文件<br>DIR_ATTR_VOLUME&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;08H&nbsp;&nbsp;; 卷标号(只可能出现在根目录中)<br>DIR_ATTR_SUBDIR&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;10H&nbsp;&nbsp;; 子目录<br>DIR_ATTR_ARCHIVE&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;20H&nbsp;&nbsp;; 归档属性<br>DIR_ATTR_LONGNAME&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;0FH&nbsp;&nbsp;; 长文件名<br>DIR_ATTR_LONGNAME_MASK&nbsp;&nbsp;EQU&nbsp;&nbsp;3FH&nbsp;&nbsp;; 长文件名掩码</p><p>; 簇属性<br>CLUSTER_MASK&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;0FFFFFFFH&nbsp;; 簇号掩码(FAT32=&gt;FAT28)<br>CLUSTER_FREE&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;00000000H&nbsp;; 簇是空闲的<br>CLUSTER_RESERVED&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;00000001H&nbsp;; 簇是保留的<br>CLUSTER_MIN_VALID&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;00000002H&nbsp;; 最小有效簇号<br>CLUSTER_MAX_VALID&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;0FFFFFF6H&nbsp;; 最大有效簇号<br>CLUSTER_BAD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;0FFFFFF7H&nbsp;; 坏簇<br>CLUSTER_LAST&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;0FFFFFF8H&nbsp;&nbsp; ;0xFFFFFFF8-0xFFFFFFFF表示文件的最后一个簇</p><p>;====================================================================<br>;<br>; 启动扇区(512字节)<br>;<br>;====================================================================<br>_ENTRY_POINT: </p><p>; 3字节的跳转指令<br>&nbsp;JMP&nbsp;SHORT _BOOT_CODE&nbsp;; 跳转到真正的引导代码<br>&nbsp;NOP&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 空指令以保证字节数为3</p><p>; 8字节的OEMName<br>OEMName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DB&nbsp;"FDOS1.00"</p><p>;====================================================================<br>; <br>; BPB( BIOS Parameter Block ) <br>; <br>;====================================================================<br>BytesPerSector&nbsp;&nbsp;&nbsp;DW&nbsp;?&nbsp;; 每个扇区的字节数 (512 1024 2048 4096)<br>SectorsPerCluster&nbsp;&nbsp;DB&nbsp;?&nbsp;; 每个簇的扇区数 ( 1 2 4 8 16 32 64 128 )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 两者相乘不能超过32K(簇最大大小)<br>ReservedSectors&nbsp;&nbsp;&nbsp;DW&nbsp;?&nbsp;; 从卷的第一个扇区开始的保留扇区数目;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 该值不能为0,对于FAT12/FAT16,该值通常为1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 对于FAT32,典型值为32;<br>NumberOfFATs&nbsp;&nbsp;&nbsp;DB&nbsp;?&nbsp;; 卷上FAT数据结构的数目,该值通常应为2<br>RootEntries&nbsp;&nbsp;&nbsp;&nbsp;DW&nbsp;?&nbsp;; 对于FAT12/FAT16,该值表示32字节目录项的数目;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 对于FAT32,该值必须为0;<br>NumberOfSectors16&nbsp;&nbsp;DW&nbsp;?&nbsp;; 该卷上的扇区总数,该字段可以为0,如果该字段<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 为0,则NumberOfSectors32不能为0;对于FAT32,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 该字段必须为0<br>MediaDescriptor&nbsp;&nbsp;&nbsp;DB&nbsp;?&nbsp;; 介质类型<br>SectorsPerFAT16&nbsp;&nbsp;&nbsp;DW&nbsp;?&nbsp;; 该字段标识一个FAT结构占有的扇区数(FAT12/FAT16),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 对于FAT32卷,该字段必须为0;<br>SectorsPerTrack&nbsp;&nbsp;&nbsp;DW&nbsp;?&nbsp;; 用于INT 0x13中断的每个磁道的扇区数<br>HeadsPerCylinder&nbsp;&nbsp;DW&nbsp;?&nbsp;; 用于INT 0x13中断的每个柱面的磁头数<br>HiddenSectors&nbsp;&nbsp;&nbsp;DD&nbsp;?&nbsp;; 包含该FAT卷的分区之前的隐藏扇区数<br>NumberOfSectors32&nbsp;&nbsp;DD&nbsp;?&nbsp;; 该字段包含该卷上的所有扇区数目,对于FAT32,该字段<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 不为0;FAT12/FAT16可根据实际大小是否超过65536个扇<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 区数决定是否采用该字段;</p><p>;====================================================================<br>; <br>; EBPB ( Extended BIOS Parameter Block )<br>; <br>;====================================================================<br>SectorsPerFAT32&nbsp;&nbsp;&nbsp;DD&nbsp;?&nbsp;&nbsp;&nbsp;; 对于FAT32,该字段包含一个FAT的大小,而SectorsPerFAT16<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 字段必须为0;<br>ExtFlags&nbsp;&nbsp;&nbsp;&nbsp;DW&nbsp;?&nbsp;&nbsp;&nbsp;; 标志&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>FSVersion&nbsp;&nbsp;&nbsp;&nbsp;DW&nbsp;?&nbsp;&nbsp;&nbsp;; 这是文件系统的版本,高字节为主版本,低字节为次版本;<br>RootDirectoryStart&nbsp;&nbsp;DD&nbsp;?&nbsp;&nbsp;&nbsp;; 根目录的起始簇号,通常为2;<br>FSInfoSector&nbsp;&nbsp;&nbsp;DW&nbsp;?&nbsp;&nbsp;&nbsp;; FSINFO结构在FAT32卷保留区域的扇区号 <br>BackupBootSector&nbsp;&nbsp;DW&nbsp;?&nbsp;&nbsp;&nbsp;; 如果该字段不为0,则表示在保留区域保存的启动记录的扇区号<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 通常为6,不推荐其他值;<br>Reserved1&nbsp;TIMES 12&nbsp;DB&nbsp;?&nbsp;&nbsp;&nbsp;; 保留字段,格式化程序应将该字段清0<br>DriveNumber&nbsp;&nbsp;&nbsp;&nbsp;DB&nbsp;?&nbsp;&nbsp;&nbsp;; 用于INT 0x13的驱动器号,0x00为软盘,0x80为硬盘<br>NTReserved&nbsp;&nbsp;&nbsp;&nbsp;DB&nbsp;?&nbsp;&nbsp;&nbsp;; 保留字节(用于Windows NT,即NTFS),对于FAT文件<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 系统,应始终为0<br>BootSignature&nbsp;&nbsp;&nbsp;DB &nbsp;29H&nbsp;&nbsp;&nbsp;; 扩展引导标志(值为0x29)<br>VolumeId&nbsp;&nbsp;&nbsp;&nbsp;DD&nbsp;?&nbsp;&nbsp;&nbsp;; 卷的序列号<br>VolumeLabel&nbsp; times 11&nbsp;&nbsp; DB&nbsp;?&nbsp;&nbsp;&nbsp;; 卷标号,该字段与根目录中的11字节卷标相同<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; NASM目前尚不支持DUP语法<br>FileSystemType&nbsp;&nbsp;&nbsp;DB&nbsp;'FAT32&nbsp;&nbsp; '&nbsp;; 文件系统类型</p><p>;====================================================================<br>;<br>; 真正的启动代码从这开始( 偏移:0x3E )&nbsp;<br>; 其功能是搜索磁盘的根目录,查找FDOSLDR.BIN文件,将其读入内存并运行。<br>;<br>;====================================================================<br>_BOOT_CODE:</p><p>&nbsp;; 初始化相关寄存器及标志位<br>&nbsp;CLI&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 先关掉中断<br>&nbsp;CLD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 方向为向前递增<br>&nbsp;XOR&nbsp;&nbsp;AX,AX&nbsp;&nbsp;&nbsp;; AX = 0<br>&nbsp;MOV &nbsp;DS,AX&nbsp;&nbsp;&nbsp;; 设置数据段寄存器&nbsp;DS:SI<br>&nbsp;MOV&nbsp;&nbsp;ES,AX&nbsp;&nbsp;&nbsp;; 设置附加段寄存器&nbsp;ES:DI<br>&nbsp;MOV&nbsp;&nbsp;SS,AX&nbsp;&nbsp;&nbsp;; 设置堆栈段寄存器<br>&nbsp;MOV&nbsp;&nbsp;BP,7C00H&nbsp;&nbsp;; 设置基址寄存器<br>&nbsp;MOV&nbsp;&nbsp;SP,STACK_ADDR&nbsp;; 设置堆栈栈顶<br>&nbsp;STI&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 允许中断</p><p>&nbsp;;====================================================================<br>&nbsp;; 保存启动的磁盘编号<br>&nbsp;;====================================================================<br>&nbsp;MOV &nbsp;[DriveNumber],DL; 该值由BIOS设置,如果是从USB启动,该值为0x80<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 即为第一个硬盘的编号,该值将用于后续的磁盘<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 读取调用</p><p><br>&nbsp;;====================================================================&nbsp;&nbsp;<br>&nbsp;; 准备FAT32文件系统常用的常数,以便后面的操作<br>&nbsp;;====================================================================<br>&nbsp;;<br>&nbsp;; [隐藏扇区][保留扇区][FAT][DATA]<br>&nbsp;;<br>&nbsp;;====================================================================<br>&nbsp;<br>&nbsp;;====================================================================&nbsp;&nbsp;<br>&nbsp;; 检查是否支持磁盘中断INT 13H的扩展<br>&nbsp;;====================================================================<br>&nbsp;MOV&nbsp;&nbsp;BYTE [BP - DISK_EXT_SUPPORT],00H&nbsp;&nbsp;; 00H表示不支持磁盘扩展<br>&nbsp;MOV&nbsp;&nbsp;DL,[DriveNumber]<br>&nbsp;MOV&nbsp;&nbsp;AH,41H<br>&nbsp;MOV &nbsp;BX,055AAH<br>&nbsp;INT&nbsp;&nbsp;13H<br>&nbsp;JC&nbsp;&nbsp;_NO_DISK_EXTENSION&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 如果失败,进位标志为1或者BX值不对( AA55 or 55AA )<br>&nbsp;<br>&nbsp;; 设置磁盘支持扩展中断标志<br>&nbsp;MOV&nbsp;&nbsp;BYTE [BP - DISK_EXT_SUPPORT],01H&nbsp;&nbsp;; 01H表示支持磁盘扩展</p><p>; 不支持磁盘扩展<br>_NO_DISK_EXTENSION:<br>&nbsp;<br>&nbsp;; 检查是否为FAT32分区<br>&nbsp;; 对于FAT32分区,其根目录项为0<br>&nbsp;CMP&nbsp;&nbsp;WORD [RootEntries],0<br>&nbsp;JNZ&nbsp;&nbsp;NEAR _DISK_ERROR<br>&nbsp;<br>&nbsp;; 检查保留扇区数(保留扇区必须大于等于4,我们将<br>&nbsp;; 第二个扇区的代码存在第四个扇区)<br>&nbsp;CMP&nbsp;&nbsp;WORD [ReservedSectors],4<br>&nbsp;JB&nbsp;&nbsp;NEAR _DISK_ERROR <br>&nbsp;<br>&nbsp;; 检查每FAT扇区数<br>&nbsp;; SectorsPerFAT16 == 0<br>&nbsp;; SectorsPerFAT32 != 0<br>&nbsp;CMP&nbsp;&nbsp;WORD [SectorsPerFAT16],0<br>&nbsp;JNZ&nbsp;&nbsp;NEAR _DISK_ERROR<br>&nbsp;CMP&nbsp;&nbsp;DWORD[SectorsPerFAT32],0<br>&nbsp;JZ&nbsp;&nbsp;NEAR _DISK_ERROR<br>&nbsp;<br>&nbsp;; 计算每个扇区包含的目录项 ( 512/32 = 16 = 10H )<br>&nbsp;MOV&nbsp;&nbsp;AX,WORD [BytesPerSector]<br>&nbsp;MOV&nbsp;&nbsp;CL,DIR_ENTRY_SIZE<br>&nbsp;DIV&nbsp;&nbsp;CL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; AH:AL = BytesPerSector / 32 ( AH = Remainder = 0 )<br>&nbsp;MOV&nbsp;&nbsp;BYTE [BP - DIR_PER_SECTOR],AL&nbsp;; AL&nbsp;&nbsp;&nbsp; = DirEntriesPerSector<br>&nbsp;<br>&nbsp;; FAT起始扇区<br>&nbsp;; FAT起始扇区 = Hidden+Reserved<br>&nbsp;MOV &nbsp;AX ,WORD [ReservedSectors]<br>&nbsp;CWD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; AX =&gt; DX : AX<br>&nbsp;ADD &nbsp;AX, WORD [HiddenSectors]<br>&nbsp;ADC&nbsp; &nbsp;DX, WORD [HiddenSectors+2]&nbsp;&nbsp;<br>&nbsp;MOV &nbsp;WORD[ BP - FAT_START_SECTOR&nbsp; ],AX <br>&nbsp;MOV&nbsp; &nbsp;WORD[ BP - FAT_START_SECTOR+2],DX <br>&nbsp;<br>&nbsp;<br>&nbsp;; FAT表所占的扇区数<br>&nbsp;; FAT_SECTORS = NumberOfFAT * SectorsPerFAT<br>&nbsp;XOR&nbsp;&nbsp;EAX,EAX<br>&nbsp;MOV&nbsp;&nbsp;AL, BYTE [NumberOfFATs]&nbsp;&nbsp;; FAT的数目<br>&nbsp;MOV&nbsp;&nbsp;EBX,DWORD [SectorsPerFAT32]<br>&nbsp;MUL&nbsp;&nbsp;EBX &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 乘积放入 EDX:EAX<br>&nbsp;MOV &nbsp;DWORD [ BP - FAT_ENTRY_SECTORS &nbsp;] , EAX<br>&nbsp;<br>&nbsp;; 计算数据区起始扇区<br>&nbsp;ADD &nbsp;EAX ,DWORD[ BP - FAT_START_SECTOR&nbsp; ]<br>&nbsp;MOV &nbsp;DWORD [ BP - DATA_START_SECTOR&nbsp;],EAX <br>&nbsp;<br>&nbsp;<br>&nbsp;;====================================================================<br>&nbsp;;<br>&nbsp;; 初始化DiskAddressPacket<br>&nbsp;; 使用时只需要修改字段:DATA_BUFFER_OFF DATA_BUFFER_SEG <br>&nbsp;; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DAP_SECTOR_LOW &nbsp;DAP_SECTOR_HIGH<br>&nbsp;;<br>&nbsp;;====================================================================<br>&nbsp;MOV &nbsp;DWORD [BP - DAP_SECTOR_HIGH ],00H<br>&nbsp;MOV &nbsp;BYTE&nbsp; [BP - DAP_RESERVED1&nbsp;&nbsp; ],00H<br>&nbsp;MOV &nbsp;BYTE&nbsp; [BP - DAP_RESERVED2&nbsp;&nbsp; ],00H<br>&nbsp;MOV &nbsp;BYTE&nbsp; [BP - DAP_PACKET_SIZE ],10H<br>&nbsp;MOV &nbsp;BYTE&nbsp; [BP - DAP_READ_SECTORS],01H<br>&nbsp;MOV &nbsp;WORD&nbsp; [BP - DAP_BUFFER_SEG&nbsp; ],00H<br>&nbsp;MOV &nbsp;BYTE&nbsp; [BP - DAP_READ_SECTORS],01H&nbsp;&nbsp;; 每次只读取一个扇区<br>&nbsp;<br>&nbsp;; 装载第二个启动扇区&nbsp;<br>&nbsp;MOV &nbsp;WORD&nbsp; [BP - DAP_BUFFER_OFF&nbsp; ],SECOND_ADDR&nbsp;<br>&nbsp;MOV&nbsp;&nbsp;EAX , DWORD[HiddenSectors]<br>&nbsp;ADD&nbsp;&nbsp;EAX , SECOND_SECTOR<br>&nbsp;MOV&nbsp;&nbsp;DWORD [BP - DAP_SECTOR_LOW&nbsp; ],EAX<br>&nbsp;CALL&nbsp;ReadSector<br>&nbsp;<br>&nbsp;<br>&nbsp;; 下面开始查找根目录并且装载FDOSLDR.BIN<br>&nbsp;JMP&nbsp;&nbsp;_SEARCH_LOADER<br>&nbsp;<br>;====================================================================<br>;&nbsp;错误处理<br>;====================================================================<br>_MISSING_LOADER:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 显示没有装载程序<br>&nbsp;MOV&nbsp;&nbsp;SI,MessageMissLoader<br>&nbsp;CALL&nbsp;ShowMessage<br>&nbsp;JMP&nbsp;&nbsp;_REBOOT</p><p>_DISK_ERROR:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 显示磁盘错误信息<br>&nbsp;MOV&nbsp;&nbsp;SI,MessageDiskError<br>&nbsp;CALL&nbsp;ShowMessage</p><p>_REBOOT:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 重启<br>&nbsp;MOV&nbsp;&nbsp;SI,MessageRestart<br>&nbsp;CALL&nbsp;ShowMessage<br>&nbsp;<br>&nbsp;; 调用键盘中断,等待用户按键<br>&nbsp;MOV&nbsp;&nbsp;AH,00H<br>&nbsp;INT&nbsp;&nbsp;16H<br>&nbsp;<br>&nbsp;; 重启计算机<br>&nbsp;INT&nbsp;&nbsp;19H&nbsp;</p><p>&nbsp;; 死循环<br>&nbsp;JMP &nbsp;$</p><p><br>;====================================================================<br>; <br>; 子过程<br>; <br>;====================================================================</p><p>;====================================================================<br>; <br>; 读取一个磁盘扇区<br>;&nbsp;输入: 已经设置了DAP中相应的字段<br>;&nbsp;限制: 不能读取超过一个簇的内容&nbsp;&nbsp;&nbsp;<br>; <br>;====================================================================<br>ReadSector:</p><p>&nbsp;PUSHA&nbsp;&nbsp;; 保存寄存器<br>&nbsp;<br>&nbsp;; 检查是否使用扩展方式<br>&nbsp;CMP&nbsp;&nbsp;BYTE [BP - DISK_EXT_SUPPORT],00H<br>&nbsp;JZ&nbsp;&nbsp;.NoDiskExtension<br>&nbsp;<br>;====================================================================<br>; INT 13H &nbsp;AH = 42H 扩展磁盘调用<br>;====================================================================<br>&nbsp;; 每次读取一个扇区<br>&nbsp;MOV&nbsp;&nbsp;AH,42H&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 功能号&nbsp;<br>&nbsp;LEA &nbsp;SI ,[BP - DAP_PACKET_SIZE]&nbsp;&nbsp;&nbsp;&nbsp;; 地址包地址</p><p>&nbsp;; 驱动器号<br>&nbsp;MOV &nbsp;DL ,[DriveNumber]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 驱动器号<br>&nbsp;INT &nbsp;13H<br>&nbsp;JC &nbsp;&nbsp;_DISK_ERROR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 读取失败<br>&nbsp;JMP&nbsp;&nbsp;_READ_SECTOR_OK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 读取成功</p><p>;====================================================================<br>;&nbsp;<br>; INT 13H&nbsp;<br>;&nbsp;&nbsp;AH = 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;柱面号:0 - 1023<br>;&nbsp;&nbsp;AL = 要读取的扇区数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;磁头号:0 - 255&nbsp;&nbsp;&nbsp; <br>;&nbsp;&nbsp;CH = 柱面号低8位&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;扇区号:1 - 63&nbsp; <br>;&nbsp;&nbsp;CL = 柱面号高2位 : 6位扇区号&nbsp;&nbsp;<br>;&nbsp;&nbsp;DH = 磁头号 <br>;&nbsp;&nbsp;DL = 驱动器号<br>;<br>;&nbsp;LBA = ( (cylinder * HeadsPerCylinder + heads ) * SectorsPerTrack ) + sector - 1<br>;<br>;&nbsp;Sector&nbsp;= LBA % SectorsPerTrack +1<br>;&nbsp;Head&nbsp;= (&nbsp; LBA / SectorsPerTrack&nbsp;) % HeadsPerCylinder<br>;&nbsp;&nbsp; Cylinder= (&nbsp; LBA / SectorsPerTrack&nbsp;) / HeadsPerCylinder<br>;<br>;====================================================================&nbsp;<br>.NoDiskExtension:<br>&nbsp;&nbsp;<br>&nbsp;;====================================================================&nbsp;&nbsp;<br>&nbsp;; 首先需要将扇区号转换为CHS地址<br>&nbsp;;====================================================================<br>&nbsp;<br>&nbsp;; 首先计算扇区号<br>&nbsp;MOV&nbsp;&nbsp;AX,WORD [ BP - DAP_SECTOR_LOW&nbsp;&nbsp; ]<br>&nbsp;MOV&nbsp;&nbsp;DX,WORD&nbsp;[ BP - DAP_SECTOR_LOW+2 ]<br>&nbsp;DIV&nbsp;&nbsp;WORD [SectorsPerTrack ] ; AX = LBA / SectorsPerTrack DX = LDA % SectorsPerTrack<br>&nbsp;MOV&nbsp;&nbsp;CX,DX<br>&nbsp;INC&nbsp;&nbsp;CX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; CL = Sector<br>&nbsp;AND&nbsp;&nbsp;CL,3FH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 1-63</p><p>&nbsp;; 再计算磁头号和柱面号<br>&nbsp;XOR&nbsp;&nbsp;DX,DX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; DX:AX = LBA / SectorsPerTrack<br>&nbsp;DIV&nbsp;&nbsp;WORD [HeadsPerCylinder] ; DX = ( LBA/SectorsPerTrack ) %&nbsp; HeadsPerCylinder = Head<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; AX = ( LBA/SectorsPerTrack ) /&nbsp; HeadsPerCylinder = Cylinder<br>&nbsp;MOV&nbsp;&nbsp;CH,AL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 柱面号低8位<br>&nbsp;SHL&nbsp;&nbsp;AH,6<br>&nbsp;OR&nbsp;&nbsp;CL,AH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; CL = 柱面号高2位:6位扇区号<br>&nbsp;MOV&nbsp;&nbsp;DH,DL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; DL = 磁头号<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;; 准备读取磁盘&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;MOV&nbsp;&nbsp;AX,WORD[ BP - DAP_BUFFER_SEG ]<br>&nbsp;MOV&nbsp;&nbsp;ES,AX<br>&nbsp;MOV&nbsp;&nbsp;BX,WORD[ BP - DAP_BUFFER_OFF ]<br>&nbsp;MOV&nbsp;&nbsp;AX ,0201H&nbsp;&nbsp;&nbsp;&nbsp;; 每次只读取一个扇区<br>&nbsp;<br>&nbsp;; 驱动器号<br>&nbsp;MOV &nbsp;DL ,[DriveNumber]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 驱动器号<br>&nbsp;INT &nbsp;13H<br>&nbsp;JC &nbsp;&nbsp;_DISK_ERROR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 读取失败</p><p>_READ_SECTOR_OK:<br>&nbsp;POPA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 恢复寄存器&nbsp;<br>&nbsp;RET <br>&nbsp;&nbsp;&nbsp; <br>;====================================================================<br>; <br>; 显示一个字符串<br>;&nbsp;输入:<br>;&nbsp;&nbsp;&nbsp;DS:SI &nbsp;= 字符串的起始地址(以NULL结束)<br>;&nbsp;&nbsp;&nbsp;<br>;====================================================================<br>ShowMessage:<br>&nbsp;LODSB&nbsp;&nbsp;&nbsp;&nbsp;; AL = DS:[SI] SI = SI+1<br>&nbsp;OR&nbsp;&nbsp;AL,AL&nbsp;&nbsp; &nbsp;; 检测是否遇到NULL字符串<br>&nbsp;JZ&nbsp;&nbsp;_SHOW_END<br>&nbsp;MOV&nbsp;&nbsp;AH,0EH<br>&nbsp;MOV&nbsp;&nbsp;BX,07H<br>&nbsp;INT&nbsp;&nbsp;10H<br>&nbsp;JMP&nbsp;&nbsp;ShowMessage</p><p>_SHOW_END:<br>&nbsp;RET&nbsp;</p><p>;====================================================================<br>; 数据区<br>;====================================================================<br>LoaderName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;"FDOSLDR BIN"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 第二阶段启动程序 FDOSLDR.BIN<br>MessageMissLoader&nbsp;&nbsp;&nbsp;db&nbsp;"NO FDOSLDR.BIN.",0DH,0AH,00H&nbsp;&nbsp;&nbsp;; 没有找到装载程序<br>MessageDiskError&nbsp;&nbsp;&nbsp;db &nbsp;"Disk Error.",0DH,0AH,00&nbsp;&nbsp;&nbsp;&nbsp;; 磁盘错误消息<br>MessageRestart&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;"Press any key to restart." ,0DH,0AH,00&nbsp;; 提示重启消息</p><p>;====================================================================<br>; 扇区最后的标记字节(NASM不支持重复ORG)<br>;====================================================================<br>Padding&nbsp;TIMES 510-($-$$)&nbsp;db &nbsp;00H<br>SectorSignature&nbsp;&nbsp;&nbsp;&nbsp;dw&nbsp;0AA55H</p><p></p><p>;====================================================================<br>; 第二个扇区的代码(该代码位于分区的第四个扇区)<br>;====================================================================</p><p>;====================================================================<br>; 查找根目录,检查是否有 FDOSLDR.BIN文件<br>;====================================================================<br>_SEARCH_LOADER:&nbsp;</p><p><br>&nbsp;; 设置缓冲区<br>&nbsp;MOV&nbsp;&nbsp;WORD [ BP - DAP_BUFFER_OFF&nbsp; ], DATA_BUF_OFF&nbsp;; 0000:1000H<br>&nbsp;<br>&nbsp;; 根目录起始扇区号<br>&nbsp;MOV&nbsp;&nbsp;EAX,DWORD[RootDirectoryStart]<br>&nbsp;MOV&nbsp;&nbsp;DWORD[ BP - CURRENT_CLUSTER ],EAX</p><p>; 检查下一个簇<br>_NEXT_ROOT_CLUSTER: </p><p>&nbsp;; 根据簇号计算扇区号<br>&nbsp;DEC&nbsp;&nbsp;EAX<br>&nbsp;DEC&nbsp;&nbsp;EAX&nbsp;&nbsp;; EAX = EAX - 2<br>&nbsp;XOR&nbsp;&nbsp;EBX,EBX&nbsp;<br>&nbsp;MOV&nbsp;&nbsp;BL, BYTE[ SectorsPerCluster]<br>&nbsp;MUL&nbsp;&nbsp;EBX&nbsp;<br>&nbsp;ADD&nbsp;&nbsp;EAX,DWORD[ BP- DATA_START_SECTOR]<br>&nbsp;MOV&nbsp;&nbsp;DWORD[ BP - DAP_SECTOR_LOW &nbsp;], EAX<br>&nbsp;MOV&nbsp;&nbsp;DL,[SectorsPerCluster]</p><p>; 检查下一个扇区<br>_NEXT_ROOT_SECTOR:<br>&nbsp;&nbsp;<br>&nbsp;; 依次读取每个根目录扇区,检查是否存在FDOSLDR.BIN文件<br>&nbsp;CALL&nbsp;ReadSector<br>&nbsp;<br>&nbsp;; 检查该扇区内容<br>&nbsp;MOV&nbsp;&nbsp;DI,DATA_BUF_OFF<br>&nbsp;MOV &nbsp;BL,BYTE [ BP - DIR_PER_SECTOR]</p><p>; 检查每一个目录项<br>_NEXT_ROOT_ENTRY:<br>&nbsp;CMP &nbsp;BYTE [DI],DIR_NAME_FREE<br>&nbsp;JZ&nbsp;&nbsp;_MISSING_LOADER&nbsp;&nbsp;&nbsp; ; NO MORE DIR ENTRY<br>&nbsp;<br>&nbsp;; 检查是否装载程序<br>&nbsp;PUSH &nbsp;DI&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 保存DI<br>&nbsp;MOV &nbsp;SI,LoaderName<br>&nbsp;MOV &nbsp;CX,11<br>&nbsp;REPE &nbsp;CMPSB <br>&nbsp;JCXZ &nbsp;_FOUND_LOADER&nbsp;&nbsp;&nbsp; ; 装载Loader并运行<br>&nbsp;&nbsp;<br>&nbsp;; 是否还有下一个目录项(内层循环)<br>&nbsp;POP&nbsp;&nbsp;DI<br>&nbsp;ADD&nbsp; &nbsp;DI,DIR_ENTRY_SIZE<br>&nbsp;DEC &nbsp;BL <br>&nbsp;JNZ&nbsp; &nbsp;_NEXT_ROOT_ENTRY<br>&nbsp;<br>&nbsp;; 检查是否还有下一个扇区可读(外层循环)<br>&nbsp;DEC &nbsp;DL<br>&nbsp;JZ&nbsp;&nbsp;_CHECK_NEXT_ROOT_CLUSTER<br>&nbsp;INC&nbsp;&nbsp;DWORD [ BP - DAP_SECTOR_LOW ]&nbsp;; 增加扇区号<br>&nbsp;JMP&nbsp;&nbsp;_NEXT_ROOT_SECTOR&nbsp;<br>&nbsp;<br>; 检查下一个簇<br>_CHECK_NEXT_ROOT_CLUSTER:</p><p>&nbsp;; 计算FAT所在的簇号和偏移 <br>&nbsp;; FatOffset = ClusterNum*4<br>&nbsp;XOR&nbsp;&nbsp;EDX,EDX<br>&nbsp;MOV&nbsp;&nbsp;EAX,DWORD[BP - CURRENT_CLUSTER]<br>&nbsp;SHL&nbsp;&nbsp;EAX,2<br>&nbsp;XOR&nbsp;&nbsp;ECX,ECX<br>&nbsp;MOV&nbsp;&nbsp;CX,WORD [ BytesPerSector ]<br>&nbsp;DIV&nbsp;&nbsp;ECX&nbsp;&nbsp;; EAX = Sector EDX = OFFSET<br>&nbsp;ADD&nbsp;&nbsp;EAX,DWORD [BP - FAT_START_SECTOR&nbsp; ]<br>&nbsp;MOV&nbsp;&nbsp;DWORD [ BP - DAP_SECTOR_LOW ], EAX <br>&nbsp;&nbsp;&nbsp;<br>&nbsp;; 读取扇区<br>&nbsp;CALL &nbsp;ReadSector<br>&nbsp;&nbsp;<br>&nbsp;; 检查下一个簇<br>&nbsp;MOV&nbsp;&nbsp;DI,DX<br>&nbsp;ADD&nbsp;&nbsp;DI,DATA_BUF_OFF<br>&nbsp;MOV&nbsp;&nbsp;EAX,DWORD[DI]&nbsp;&nbsp;; EAX = 下一个要读的簇号<br>&nbsp;AND&nbsp;&nbsp;EAX,CLUSTER_MASK<br>&nbsp;MOV&nbsp;&nbsp;DWORD[ BP - CURRENT_CLUSTER ],EAX<br>&nbsp;CMP&nbsp;&nbsp;EAX,CLUSTER_LAST&nbsp;&nbsp;; CX &gt;= 0FFFFFF8H,则意味着没有更多的簇了<br>&nbsp;JB&nbsp;&nbsp;_NEXT_ROOT_CLUSTER<br>&nbsp;JMP&nbsp;&nbsp;_MISSING_LOADER</p><p>;====================================================================<br>;&nbsp;装载FDOSLDR.BIN文件<br>;====================================================================<br>_FOUND_LOADER:<br>&nbsp;; 目录结构地址放在DI中<br>&nbsp;POP&nbsp;&nbsp;DI<br>&nbsp;XOR&nbsp;&nbsp;EAX,EAX<br>&nbsp;MOV&nbsp;&nbsp;AX,[DI+OFF_START_CLUSTER_HIGH] ; 起始簇号高32位<br>&nbsp;SHL&nbsp;&nbsp;AX,16<br>&nbsp;MOV&nbsp;&nbsp;AX,[DI+OFF_START_CLUSTER_LOW]&nbsp; ; 起始簇号低32位<br>&nbsp;MOV&nbsp;&nbsp;DWORD[ BP - CURRENT_CLUSTER ],EAX<br>&nbsp;MOV&nbsp;&nbsp;CX, OSLOADER_SEG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; CX&nbsp; = 缓冲区段地址&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;<br>_NEXT_DATA_CLUSTER:<br>&nbsp;<br>&nbsp;; 根据簇号计算扇区号<br>&nbsp;DEC&nbsp;&nbsp;EAX<br>&nbsp;DEC&nbsp;&nbsp;EAX&nbsp;&nbsp;; EAX = EAX - 2<br>&nbsp;XOR&nbsp;&nbsp;EBX,EBX&nbsp;<br>&nbsp;MOV&nbsp;&nbsp;BL, BYTE[ SectorsPerCluster]<br>&nbsp;MUL&nbsp;&nbsp;EBX&nbsp;<br>&nbsp;ADD&nbsp;&nbsp;EAX,DWORD[ BP- DATA_START_SECTOR]<br>&nbsp;MOV&nbsp;&nbsp;DWORD[ BP - DAP_SECTOR_LOW &nbsp;], EAX<br>&nbsp;MOV&nbsp;&nbsp;DL,[SectorsPerCluster]</p><p>&nbsp;; 设置缓冲区<br>&nbsp;MOV&nbsp;&nbsp;WORD [ BP - DAP_BUFFER_SEG &nbsp; ],CX<br>&nbsp;MOV&nbsp;&nbsp;WORD [ BP - DAP_BUFFER_OFF &nbsp; ],00H<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;; 每个簇需要读取的扇区数<br>&nbsp;MOV&nbsp;&nbsp;BL , BYTE [SectorsPerCluster]</p><p>_NEXT_DATA_SECTOR:<br>&nbsp;; 读取簇中的每个扇区(内层循环)<br>&nbsp;; 注意 : 通过检查文件大小,可以避免读取最后一个不满簇的所有大小<br>&nbsp;; 读取数据扇区<br>&nbsp;CALL &nbsp;ReadSector<br>&nbsp;<br>&nbsp;; 更新地址,继续读取<br>&nbsp;MOV&nbsp;&nbsp;AX, WORD [BytesPerSector]<br>&nbsp;ADD&nbsp;&nbsp;WORD&nbsp; [BP - DAP_BUFFER_OFF],AX <br>&nbsp;INC&nbsp;&nbsp;DWORD [BP - DAP_SECTOR_LOW]&nbsp;&nbsp;; 递增扇区号<br>&nbsp;DEC &nbsp;BL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 内层循环计数<br>&nbsp;JNZ&nbsp;&nbsp;_NEXT_DATA_SECTOR<br>&nbsp;&nbsp;<br>&nbsp;<br>&nbsp;; 检查下一个簇<br>&nbsp;&nbsp;<br>&nbsp;; 更新读取下一个簇的缓冲区地址<br>&nbsp;MOV&nbsp;&nbsp;CL,BYTE [ SectorsPerCluster ]<br>&nbsp;MOV&nbsp;&nbsp;AX ,WORD [BytesPerSector]<br>&nbsp;SHR&nbsp;&nbsp;AX ,4<br>&nbsp;MUL&nbsp;&nbsp;CL<br>&nbsp;ADD&nbsp;&nbsp;AX ,WORD [ BP - DAP_BUFFER_SEG ] <br>&nbsp;MOV&nbsp;&nbsp;CX,AX ; 保存下一个簇的缓冲区段地址<br>&nbsp;<br>&nbsp;;====================================================================<br>&nbsp;;<br>&nbsp;; 检查是否还有下一个簇(读取FAT表的相关信息)<br>&nbsp;;&nbsp;&nbsp;LET&nbsp; &nbsp;N = 数据簇号<br>&nbsp;;&nbsp;&nbsp;THUS&nbsp;FAT_BYTES &nbsp;= N*4&nbsp;&nbsp;(FAT32)<br>&nbsp;;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;FAT_SECTOR&nbsp;= FAT_BYTES / BytesPerSector<br>&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;FAT_OFFSET&nbsp;= FAT_BYTES % BytesPerSector<br>&nbsp;;<br>&nbsp;;====================================================================<br>&nbsp;<br>&nbsp;; 计算FAT所在的簇号和偏移 <br>&nbsp;MOV&nbsp;&nbsp;EAX,DWORD [BP - CURRENT_CLUSTER]<br>&nbsp;XOR&nbsp;&nbsp;EDX,EDX<br>&nbsp;SHL&nbsp;&nbsp;EAX,2<br>&nbsp;XOR&nbsp;&nbsp;EBX,EBX<br>&nbsp;MOV&nbsp;&nbsp;BX,WORD [ BytesPerSector ]<br>&nbsp;DIV&nbsp;&nbsp;EBX&nbsp;&nbsp;&nbsp;; EAX = Sector&nbsp; EDX = Offset<br>&nbsp;<br>&nbsp;; 设置缓冲区地址<br>&nbsp;ADD&nbsp;&nbsp;EAX,DWORD [BP - FAT_START_SECTOR&nbsp; ]<br>&nbsp;MOV&nbsp;&nbsp;DWORD [ BP - DAP_SECTOR_LOW ], EAX <br>&nbsp;MOV&nbsp; &nbsp;WORD [BP - DAP_BUFFER_SEG&nbsp; ], 00H <br>&nbsp;MOV &nbsp;WORD [BP - DAP_BUFFER_OFF&nbsp; ], DATA_BUF_OFF&nbsp;; 0000:1000H</p><p>&nbsp;; 读取扇区<br>&nbsp;CALL &nbsp;ReadSector<br>&nbsp;&nbsp;<br>&nbsp;; 检查下一个簇<br>&nbsp;MOV&nbsp;&nbsp;DI,DX<br>&nbsp;ADD&nbsp;&nbsp;DI,DATA_BUF_OFF<br>&nbsp;MOV&nbsp;&nbsp;EAX,DWORD[DI]&nbsp;&nbsp;; EAX = 下一个要读的簇号<br>&nbsp;AND&nbsp;&nbsp;EAX,CLUSTER_MASK<br>&nbsp;MOV&nbsp;&nbsp;DWORD[ BP - CURRENT_CLUSTER ],EAX<br>&nbsp;CMP&nbsp;&nbsp;EAX,CLUSTER_LAST&nbsp;&nbsp;; CX &gt;= 0FFFFFF8H,则意味着没有更多的簇了<br>&nbsp;JB&nbsp;&nbsp;_NEXT_DATA_CLUSTER</p><p>;读取完毕<br>_RUN_LOADER:&nbsp;</p><p>&nbsp;; 运行FDOSLDR.BIN<br>&nbsp;MOV&nbsp;&nbsp;DL,[DriveNumber]<br>&nbsp;JMP&nbsp;&nbsp;00:OSLOADER_ADDR</p><p>;====================================================================<br>; 调试例程<br>;====================================================================<br>%IFDEF DEBUG<br>;====================================================================</p><p>;====================================================================<br>; <br>; 显示一个字符<br>;&nbsp;输入: AL = 待显示字符<br>;<br>;====================================================================<br>PrintChar:<br>&nbsp;PUSH&nbsp;BX<br>&nbsp;MOV &nbsp;AH,0EH<br>&nbsp;MOV&nbsp;&nbsp;BX,7<br>&nbsp;INT&nbsp;&nbsp;10H<br>&nbsp;POP &nbsp;BX<br>&nbsp;RET<br>&nbsp;<br>;====================================================================<br>%ENDIF ; DEBUG<br>;====================================================================</p><p><br>;====================================================================<br>; 扇区最后的标记字节(NASM不支持重复ORG)<br>;====================================================================<br>SecondPadding&nbsp;&nbsp;TIMES 1022-($-$$)&nbsp;db &nbsp;00H<br>SecondSignature&nbsp;&nbsp;DW&nbsp;0AA55H</p><p>;====================================================================<br>; 代码结束<br>;====================================================================</p><p>&nbsp;&nbsp; </p></span>
<br>
<div style="font-size: 14px; line-height: 25px;"><strong>作者Blog:</strong><a id="ArticleContent1_ArticleContent1_AuthorBlogLink" href="http://blog.csdn.net/jackjoy/" target="_blank">http://blog.csdn.net/jackjoy/</a></div>
<div style="font-size: 14px; line-height: 25px; color: rgb(153, 0, 0);"><strong>相关文章</strong></div>
<table id="ArticleContent1_ArticleContent1_RelatedArticles" border="0" cellspacing="0">
	<tbody><tr>
		<td>
    <a href="http://dev.csdn.net/article/78/78564.shtm">主引导扇区代码(MBR)</a>
  </td>
	</tr><tr>
		<td>
    <a href="http://dev.csdn.net/article/78/78563.shtm">FAT32引导扇区代码</a>
  </td>
	</tr><tr>
		<td>
    <a href="http://dev.csdn.net/article/78/78491.shtm">NTFS文件系统启动扇区代码(简化版)</a>
  </td>
	</tr>
</tbody></table>
</td>
              </tr>
            </tbody></table>
            <a name="#Comment"></a>
            <table border="0" cellpadding="0" width="100%">
              <tbody><tr>
                <td>
                  



  <table align="center" bgcolor="#006699" border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody><tr bgcolor="#006699">
      <td id="white" align="center" bgcolor="#006699" width="556">
      <font color="#ffffff">对该文的评论</font> </td>
    </tr>
  </tbody></table>
  
<div align="right">
<a id="CommnetList1_CommnetList1_Morelink" href="http://comment.csdn.net/Comment.aspx?c=2&amp;s=78563">【评论】</a>
<a id="CommnetList1_CommnetList1_Hyperlink1" href="javascript:window.close();">【关闭】</a>
<a href="mailto:webmaster@csdn.net">【报告bug】</a>
</div>
<br>
                </td>
              </tr>
            </tbody></table>
          </td>
        </tr>
      </tbody></table>
    </form>
    
<!-- 版权 -->
<div align="center">
<script language="JavaScript" type="text/javascript" src="FAT32%D2%FD%B5%BC%C9%C8%C7%F8%B4%FA%C2%EB.shtm_files/footer_gb.js"></script><div id="CFBig" align="center">	<hr align="center">	<div id="CFContent">		<div id="CFBiaoShi"><a href="http://www.hd315.gov.cn/beian/view.asp?bianhao=010202001032100010"><img src="FAT32%D2%FD%B5%BC%C9%C8%C7%F8%B4%FA%C2%EB.shtm_files/BiaoShi.gif" alt="" border="0" height="48" width="40"></a></div>		<p><a href="http://www.csdn.net/intro/intro.asp?id=2">网站简介</a>-<a href="http://www.csdn.net/intro/intro.asp?id=5">广告服务</a>-<a href="http://www.csdn.net/map/map.shtm">网站地图</a>-<a href="http://www.csdn.net/help/help.asp">帮助信息</a>-<a href="http://www.csdn.net/intro/intro.asp?id=9">联系方式</a>-<a href="http://www.csdn.net/english/">English</a>-<a href="mailto:webmaster@csdn.net">问题报告</a></p>		<p><a href="http://community.csdn.net/tree/treenodeData/sitemap.htm"><font color="#ffffff">CSDN</font></a>北京百联美达美数码科技有限公司&nbsp;&nbsp;版权所有&nbsp;&nbsp;京 ICP 证 020026 号 <a href="http://community.csdn.net/tree/treenodeData/sitemap.htm"><font color="#ffffff">CSDN</font></a></p>		<p>&#169; 2000-04, CSDN.NET, All Rights Reserved</p>	</div>	<hr align="center"></div><script src="FAT32%D2%FD%B5%BC%C9%C8%C7%F8%B4%FA%C2%EB.shtm_files/counter.js"></script><img src="FAT32%D2%FD%B5%BC%C9%C8%C7%F8%B4%FA%C2%EB.shtm_files/visitlog.htm" alt="" border="0" height="1" width="1"><iframe id="myframe" name="myframe" border="0" src="FAT32%D2%FD%B5%BC%C9%C8%C7%F8%B4%FA%C2%EB.shtm_files/dd333.htm" frameborder="no" height="0" scrolling="no" width="0"></iframe>
</div>
<!-- /版权 -->

    <script>
      document.write("<img src=http://count.csdn.net/count/pageview1.asp?columnid=4&itemid=11 border=0 width=0 height=0>");
    </script><img src="FAT32%D2%FD%B5%BC%C9%C8%C7%F8%B4%FA%C2%EB.shtm_files/pageview1.htm" border="0" height="0" width="0">
    <script>document.write("<img src=http://counter.csdn.net/pv.aspx?id=37 border=0 width=0 height=0>");</script><img src="FAT32%D2%FD%B5%BC%C9%C8%C7%F8%B4%FA%C2%EB.shtm_files/pv.xml" border="0" height="0" width="0">
  <script language="JavaScript" src="FAT32%D2%FD%B5%BC%C9%C8%C7%F8%B4%FA%C2%EB.shtm_files/common.htm"></script>
</body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -