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

从Bootloader跳转到硬盘第二扇区失败的技术问题排查

问题分析与修复方案

1. 核心错误:跳转目标与代码存储位置不匹配

你把outside函数写在了主引导扇区的代码末尾,但BIOS只会加载硬盘第一扇区(主引导扇区)到内存0x7c00,第二扇区需要手动读取到0x9000。当前代码里的jmp outside是跳转到主引导扇区代码内的标签,而这个标签所在的内存区域根本没被加载,跳转后必然跑飞。

修复:

  • 把outside函数从主引导程序中移除,单独放到第二扇区的代码文件中。
  • 跳转时直接指向读取第二扇区的内存地址:jmp 0x9000(对应你设置的es:bx = 0x0000:0x9000物理地址)。

2. 磁盘读取函数的参数混淆问题

disc_read函数中,你用dh传递要读取的扇区数,但之后又用dh设置磁头号,虽然有push dx/pop dx保存恢复,但逻辑易混淆。此外,错误字符串用dw定义会导致显示乱码(print函数按字节读取,dw是按字存储),让你看不到读盘错误提示。

修复后的disc_read.s:

disc_read:
    pusha
    push dx         ; 保存原始dx(dh=扇区数,dl=BIOS传入的驱动器号)
    mov ah, 0x02    ; INT 13h读扇区功能号
    mov al, dh      ; 要读取的扇区数
    mov cl, 0x02    ; 起始扇区号(第二扇区)
    mov ch, 0x00    ; 柱面号
    mov dh, 0x00    ; 磁头号
    int 0x13        ; 执行读盘
    jc disc_error
    pop dx
    cmp al, dh      ; 校验实际读取扇区数
    jne sectors_error
    popa
    ret

disc_error:
    mov bx, disc_error_str
    call print
    call print_nl
    jmp $
sectors_error:
    mov bx, sectors_error_str
    call print
    call print_nl
    jmp $

; 用db按字节存储字符串,避免乱码
sectors_error_str: db "Incorrect number of sectors read", 0
disc_error_str: db "Disc read error", 0

3. 主引导程序结构修正

主引导扇区必须严格控制在512字节内,末尾是0xaa55签名。移除原代码中outside相关内容,确保签名前的代码不超过510字节。

修改后的主引导程序(boot.asm):

[org 0x7c00]
    mov bp, 0x8000 
    mov sp, bp
    mov bx, 0x9000 
    mov dh, 1       ; 只读取第二扇区,设为1即可
    call disc_read
    jmp 0x9000      ; 跳转到第二扇区的内存地址
    jmp $

%include "src/disc_read.s"
%include "src/print.s"
hello_World_str: db "Welcome", 0

; 填充到510字节,加上签名刚好512字节
times 510 - ($-$$) db 0
dw 0xaa55 

4. 独立的第二扇区代码(second_sector.s)

创建单独的第二扇区文件,存放outside函数:

[org 0x9000]    ; 对应读取到的内存地址
outside:
    mov ah, 0x0e
    mov al, 0x41    ; 显示字符'A'
    int 0x10
    jmp $           ; 无限循环

times 512 - ($-$$) db 0  ; 填充到512字节,保证是完整扇区

编译与测试步骤

  1. 编译主引导程序:nasm boot.asm -f bin -o boot.bin
  2. 编译第二扇区:nasm second_sector.s -f bin -o second.bin
  3. 合并成磁盘镜像:
    • Windows:copy /b boot.bin + second.bin disk.img
    • Linux/macOS:cat boot.bin second.bin > disk.img
  4. 用虚拟机或模拟器加载disk.img测试

修复后,主引导程序会读取第二扇区到0x9000,跳转后执行outside函数,显示字符'A'并进入无限循环,符合预期。

内容的提问来源于stack exchange,提问作者em3rald1

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 19:10:17