x86汇编引导加载程序读取NTFS磁盘kernel.bin的技术求助
解决方案:在NTFS磁盘上从引导加载器读取kernel.bin
BIOS中断int 0x13仅负责底层扇区读写,无法识别NTFS这类文件系统的结构。要读取同一分区下的kernel.bin,你需要自己实现NTFS核心结构的解析逻辑,找到文件对应的扇区后再用int 0x13读取到内存。以下是具体步骤和代码方向:
核心思路
- 定位NTFS分区:从MBR(主引导记录)的分区表中找到类型为
0x07的NTFS分区,获取其起始LBA地址。 - 读取NTFS引导扇区:读取NTFS分区的第一个扇区,从中提取关键参数(簇大小、MFT起始位置等)。
- 定位kernel.bin的MFT记录:遍历MFT(主文件表)或根目录条目,找到对应
kernel.bin的MFT记录。 - 解析文件数据流:从MFT记录中提取
$DATA属性,获取文件占用的扇区范围(连续或非连续的运行列表)。 - 读取并执行内核:用
int 0x13的LBA模式读取文件扇区到内存指定位置,跳转执行。
代码修改示例(第一步:定位NTFS分区)
BITS 16 ORG 0x7C00 jmp short strt nop ; 占位符,兼容MBR结构要求 strt: ; 初始化段寄存器和栈 mov ax, 0x0000 mov ds, ax mov es, ax mov ss, ax mov sp, 0x7C00 ; 设置640x480视频模式 mov ah, 00h mov al, 12h int 0x10 ; 遍历MBR分区表找NTFS分区 mov si, 0x7C00 + 0x1BE ; 第一个分区项起始偏移 find_ntfs_part: mov al, [si + 4] ; 读取分区类型字节 cmp al, 0x07 ; NTFS分区类型标识 je ntfs_part_found add si, 16 ; 下一个分区项(每个16字节) cmp si, 0x7C00 + 0x1BE + 64 ; 4个分区项总长度 jb find_ntfs_part ; 未找到NTFS分区,报错 mov ah, 0x0E mov al, 'E' int 0x10 jmp $ ntfs_part_found: ; 保存NTFS分区起始LBA(小端序4字节) mov eax, [si + 8] mov [ntfs_start_lba], eax ; 用LBA模式读取NTFS引导扇区到0x8000 mov ah, 0x42 ; BIOS LBA读取函数 mov dl, 0x80 ; 第一块物理硬盘 mov si, dap ; 磁盘访问包指针 mov dword [dap + 8], eax ; 填充NTFS分区起始LBA int 0x13 jc read_error ; 读取失败跳转 ; 后续步骤:解析NTFS引导扇区、定位MFT、查找kernel.bin... jmp main read_error: mov ah, 0x0E mov al, 'R' int 0x10 jmp $ ; 磁盘访问包(DAP)结构 dap: db 0x10 ; DAP大小(固定16字节) db 0 ; 保留位 dw 1 ; 要读取的扇区数 dd 0x8000 ; 目标内存地址(ES:BX,这里ES=0即0x0000:0x8000) dq 0 ; 起始LBA地址(后续填充) ntfs_start_lba dd 0 ; 存储NTFS分区起始LBA main: jmp $ times 510-($-$$) db 0 dw 0xAA55
后续关键步骤提示
- 解析NTFS引导扇区:从
0x8000地址读取引导扇区,提取BPB_BytsPerSec(每扇区字节数)、BPB_SecPerClus(每簇扇区数)、BPB_MftStartLcn(MFT起始簇)等参数。 - 读取MFT记录:根据MFT起始簇计算LBA地址,读取MFT的第一个簇,找到根目录的MFT记录(通常是记录号5)。
- 查找kernel.bin:遍历根目录的
$FILE_NAME属性条目,匹配文件名kernel.bin,获取对应的MFT记录号。 - 读取文件内容:解析目标MFT记录的
$DATA属性,若文件连续则直接读取对应扇区;若非连续则解析运行列表(Run List),逐个读取分散的扇区。
注意事项
- NTFS结构复杂,需处理属性偏移、记录扩展、运行列表解析等细节,建议参考NTFS官方文档精简实现。
- 实模式下内存限制在1MB以内,需合理规划内存布局(比如把内核加载到
0x1000:0000或更高地址)。 - 测试时优先使用虚拟机(QEMU/VirtualBox),避免损坏真实磁盘数据。
内容的提问来源于stack exchange,提问作者ja0
相关产品推荐
相关产品推荐

