为何使用INT 13h AH=42h从CD-ROM读取引导加载器失败?求助排查
CD-ROM引导加载器读取问题排查与修复
问题背景
我尝试从CD-ROM读取OS引导加载器代码,采用INT 13h AH=42h(扩展扇区读取功能)实现。制作ISO文件后在两台虚拟机测试均出现异常:
- 在QEMU x86_64虚拟机中,提示“OS boot successfully copied to HDD!”,说明CD-ROM读取无错误且已完成硬盘写入,但检查硬盘时找不到引导加载器代码;
- 在VMware x86虚拟机中,直接显示“CDRE”,说明CD-ROM读取过程出错。
对比测试:使用INT 13h AH=2h从软盘启动时,两台虚拟机均正常运行。
相关代码如下:
try_read_os_from_cd: mov ah, 42h mov dl, e0h mov si, DAP_table int 13h jnc print_copy_boot_msg print 'C' print 'D' print 'R' print 'E' print_copy_boot_msg: println_string OS_boot_coping_started ; println is a macro try_write_boot_to_hdd: mov ax, 0 call l2hts ;l2hts converts LBA address to CHS address xor ax, ax mov es, ax mov bx, os_boot_hdd mov ah, 3h mov al, 1 mov dl, 80h int 13h jnc success_copy print 'H' print 'W' print 'E' DAP_table: db 16 db 0 dw 1 dw os_boot_hdd dw 0 dq 1 times 510-($-$$) db 0 db 0x55, 0xaa os_boot_hdd:
问题根源分析
VMware读取失败原因:
- 硬编码驱动器号
dl = e0h不可靠。BIOS启动时会将当前启动设备的驱动器号加载到dl寄存器,硬编码会导致设备不匹配,触发读取错误; - 未提前检测BIOS是否支持
INT 13h扩展功能。调用AH=42h前需验证扩展功能可用性,部分环境默认不支持该指令。
- 硬编码驱动器号
QEMU写入后硬盘无内容原因:
- DAP表段地址逻辑不严谨。虽DAP表中设置了段地址
dw 0,但读取时未显式指定es=0,可能导致数据写入到错误内存区域; - CHS转换函数
l2hts可能存在逻辑错误。若LBA转CHS的磁头、柱面、扇区参数计算错误,会导致写入到硬盘的无效位置。
- DAP表段地址逻辑不严谨。虽DAP表中设置了段地址
修复方案
1. 修复驱动器号与功能检测
try_read_os_from_cd: ; 先检测INT 13h扩展功能是否可用 mov ah, 41h mov bx, 55AAh int 13h jc cd_ext_not_supported ; 不支持则报错 cmp bx, 0AA55h jne cd_ext_not_supported ; 使用BIOS传入的启动设备号dl,不硬编码 mov ah, 42h mov si, DAP_table int 13h jnc print_copy_boot_msg print 'C' print 'D' print 'R' print 'E' jmp hang cd_ext_not_supported: print 'EXT' hang: jmp hang
2. 修正DAP表与写入逻辑
确保DAP表段地址与写入时的段寄存器一致,同时校验CHS转换逻辑:
DAP_table: db 16 ; DAP大小 db 0 ; 保留位 dw 1 ; 读取扇区数 dw os_boot_hdd; 偏移地址 dw 0 ; 段地址(与写入时的es=0对应) dq 1 ; LBA起始扇区(需确认CD-ROM镜像的LBA起始值,部分镜像从0开始) try_write_boot_to_hdd: ; 确认写入硬盘的LBA地址(此处为LBA 0) mov ax, 0 ; 传入LBA地址,需匹配l2hts函数参数要求 call l2hts ; 转换为CHS,确保函数正确设置ch、cl、dh寄存器 xor ax, ax mov es, ax mov bx, os_boot_hdd mov ah, 3h ; 写扇区功能 mov al, 1 ; 写入1个扇区 mov dl, 80h ; 主硬盘 int 13h jnc success_copy print 'H' print 'W' print 'E' jmp hang
3. 额外注意事项
- CD-ROM镜像需符合ISO 9660或El Torito规范,确保BIOS能识别为可启动设备;
- 确认
l2hts函数逻辑正确:柱面= LBA/(磁头数×每柱面扇区数),磁头=(LBA/每柱面扇区数)%磁头数,扇区=(LBA%每柱面扇区数)+1; - 调试时可添加寄存器打印逻辑,验证
INT 13h调用前后的寄存器值是否符合预期。
内容的提问来源于stack exchange,提问作者Demtim
相关产品推荐
相关产品推荐

