自制OS启动加载器Disk Read error磁盘读取错误修复问询
磁盘读取错误(Disk Read error)修复方案
问题描述
在构建简易操作系统时,调用磁盘加载函数出现Disk Read error,调试发现ah寄存器值为0xc(对应BIOS磁盘错误码:无效介质或磁道未找到)。尝试在int 0x13前添加xor bx, bx; mov es, bx后程序挂起。
相关代码
boot_sect.asm
[org 0x7c00] KERNEL_OFFSET equ 0x1000 mov [BOOT_DRIVE], dl mov bp, 0x9000 mov sp, bp mov bx, MSG_REAL_MODE call print_string call load_kernel mov bx, MSG_LOAD_KERNEL call print_string call switch_to_pm jmp $ %include "print_string.asm" %include "disk_load.asm" %include "gdt.asm" %include "print_string_pm.asm" %include "switch_to_pm.asm" [bits 16] load_kernel: mov bx, MSG_LOAD_KERNEL call print_string mov bx, KERNEL_OFFSET mov dh, 15 mov dl, [BOOT_DRIVE] call disk_load ret [bits 32] BEGIN_PM: mov ebx, MSG_PROT_MODE call print_string_pm call KERNEL_OFFSET jmp $ BOOT_DRIVE db 0 MSG_REAL_MODE db "Started in 16-bit Real Mode", 0 MSG_PROT_MODE db "Successfully landed in 32-bit Protected Mode", 0 MSG_LOAD_KERNEL db "Loading kernel into memory", 0 ; Padding times 510-($-$$) db 0 dw 0xaa55
disk_load.asm
; load DH sectors to ES:BX from drive DL disk_load : push dx ; Store DX on stack so later we can recall ; how many sectors were request to be read , ; even if it is altered in the meantime mov ah, 0x02 ; BIOS read sector function mov al, dh ; Read DH sectors mov ch, 0x00 ; Select cylinder 0 mov dh, 0x00 ; Select head 0 mov cl, 0x02 ; Start reading from second sector ( i.e. ; after the boot sector ) int 0x13; BIOS interrupt jc disk_error ; Jump if error ( i.e. carry flag set ) pop dx ; Restore DX from the stack cmp dh, al ; if AL ( sectors read ) != DH ( sectors expected ) jne disk_error2 ; display error message ret disk_error : mov bx , DISK_ERROR_MSG call print_string jmp $ disk_error2 : mov bx , DISK_ERROR_MSG2 call print_string jmp $ ; Variables DISK_ERROR_MSG db " Disk read error 1 !" , 0 DISK_ERROR_MSG2 db " Disk read error 2 !" , 0
编译命令
i386-elf-gcc -ffreestanding -c kernel.c -o kernel.o ld -m elf_i386 -o kernel.bin -Ttext 0x1000 kernel.o --oformat binary nasm boot_sect.asm -f bin -o boot_sect.bin cat boot_sect.bin kernel.bin > os-image qemu-system-x86_64 os-image
修复方案
BIOS中断0x13的错误码0xc表示无效介质或磁道未找到,结合代码和操作流程,问题可通过以下步骤修复:
正确设置段寄存器ES
BIOS磁盘读取依赖ES:BX作为目标地址,需在设置BX前初始化ES,避免破坏目标地址:load_kernel: mov bx, MSG_LOAD_KERNEL call print_string xor bx, bx mov es, bx ; 将ES设置为0x0000 mov bx, KERNEL_OFFSET ; 此时ES:BX = 0x0000:0x1000,对应物理地址0x1000 mov dh, 15 mov dl, [BOOT_DRIVE] call disk_load ret验证并匹配扇区读取数量
若kernel.bin实际大小不足15*512=7680字节,QEMU会因读取不存在的扇区报错。可调整dh为实际需要的扇区数,或生成镜像后填充空扇区:truncate -s 7680 os-image添加磁盘读取重试机制
BIOS磁盘操作偶尔会失败,增加重试逻辑提升可靠性:disk_load : push dx mov cx, 3 ; 重试3次 retry: mov ah, 0x02 mov al, dh mov ch, 0x00 mov dh, 0x00 mov cl, 0x02 int 0x13 jnc success ; 无错误则跳转 dec cx jnz retry ; 还有重试次数则重试 jc disk_error ; 所有重试失败,报错 success: pop dx cmp dh, al jne disk_error2 ret明确指定QEMU磁盘格式
启动QEMU时指定软盘格式,避免自动识别错误:qemu-system-x86_64 -drive format=raw,file=os-image,index=0,if=floppy
内容的提问来源于stack exchange,提问作者unp1ng46l3
相关产品推荐
相关产品推荐

