You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自制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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 05:34:56