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

Bootloader无法跳转至Stage 2显示消息的问题排查求助

32位内核Bootloader Stage1到Stage2跳转失败问题排查

我正在为32位内核开发Bootloader,遇到了Stage 1到Stage 2的跳转异常问题,代码未按预期跳转至Stage 2执行。使用NASM汇编、QEMU仿真,已通过HxD验证.img文件内容,但QEMU运行时Stage 2的消息Hello from Stage 2! :)并未显示。

Bootloader设计逻辑:

  1. 配置段寄存器和栈;
  2. 从磁盘读取Stage 2至内存;
  3. 跳转至Stage 2的加载地址执行。

相关代码与构建文件

Stage 1 代码

[BITS 16]               ; 工作在16位实模式
[org 0x7c00]            ; BIOS加载Bootloader的起始物理地址

start:                  ; 代码入口点
    jmp main            ; 跳过数据区,直接执行主逻辑

main:                   ; Bootloader主程序开始

    ; -------------------------
    ; 设置段寄存器
    ; -------------------------
    cli                 ; 关闭中断,避免段寄存器设置被干扰
    mov ax, 0x7C0       ; AX = 0x7C0,对应物理地址0x7C00(0x7C0*16)
    mov ds, ax          ; 数据段指向Bootloader所在内存
    mov es, ax          ; 附加段指向Bootloader所在内存
    mov fs, ax          ; FS段设置
    mov gs, ax          ; GS段设置

    ; -------------------------
    ; 设置栈
    ; -------------------------
    xor ax, ax          ; AX清零
    mov ss, ax          ; 栈段设为0
    mov sp, 0xFFFF      ; 栈指针指向内存顶部,栈向下生长

    sti                 ; 重新启用中断

    ; -------------------------
    ; 从磁盘加载Stage 2
    ; -------------------------
    mov ah, 02h         ; BIOS INT13h功能:读磁盘扇区
    mov al, 01h         ; 读取1个扇区(注释写63扇区,与实际值不符)

    mov ch, 00h         ; 柱面号0(注释写1,与实际值不符)
    mov cl, 02h         ; 扇区号2(从1开始计数)
    mov dh, 00h         ; 磁头号0
    mov dl, 0x80        ; 目标磁盘:第一块硬盘

    mov es, ax          ; ES设为0x7C0
    mov bx, 0x8000      ; BX设为0x8000,ES:BX指向物理地址0xFC00

    int 13h             ; 调用BIOS中断读磁盘

    jc disk_read_error  ; 若读盘失败(进位标志置位),跳转到错误处理

pass:                   ; 读盘成功后执行
    jmp 0x0800:0x0000   ; 跳转至物理地址0x8000(与加载地址不匹配)

disk_read_error:
    int 18h             ; 调用INT18h尝试其他引导方式
TIMES 510-($-$$) DB 0   ; 填充至512字节
DW 0xAA55               ; BIOS引导签名

Stage 2 代码

[BITS 16]
[ORG 0x8000]

start:
    mov si, message
    call print_string

    cli
    hlt

print_string:
    mov ah, 0x0E
.next_char:
    lodsb
    cmp al, 0
    je done
    int 0x10
    jmp .next_char

done:
    ret

message db "Hello from Stage 2! :)", 0

TIMES 510-($-$$) db 0   ; 冗余的引导扇区填充
DW 0xAA55               ; 冗余的引导签名

Makefile

PROJECT_ROOT := $(CURDIR)

STAGE1_SRC := $(PROJECT_ROOT)\Boot\Stage1\stage1.asm
STAGE2_SRC := $(PROJECT_ROOT)\Boot\Stage2\stage2.asm

STAGE1_BIN := $(PROJECT_ROOT)\Boot\Stage1\stage1.bin
STAGE2_BIN := $(PROJECT_ROOT)\Boot\Stage2\stage2.bin

IMG := C:\Users\ilanv\OS_32Bit\Code\bootloader.img

QEMU_IMG := "C:/QEMU/qemu-img.exe"
DD := "C:/dd/dd.exe"

output: $(STAGE1_BIN) $(STAGE2_BIN) $(IMG)

$(STAGE1_BIN): $(STAGE1_SRC)
    @echo "Assembling Stage 1..."
    nasm -f bin "$(STAGE1_SRC)" -o "$(STAGE1_BIN)"

$(STAGE2_BIN): $(STAGE2_SRC)
    @echo "Assembling Stage 2..."
    nasm -f bin "$(STAGE2_SRC)" -o "$(STAGE2_BIN)"

$(IMG): $(STAGE1_BIN) $(STAGE2_BIN)
    @echo "Creating bootloader.img..."
    $(QEMU_IMG) create -f raw "$(IMG)" 10M
    $(DD) if=$(STAGE1_BIN) of=$(IMG) bs=512 count=1
    $(DD) if=$(STAGE2_BIN) of=$(IMG) bs=512 seek=1

clean:
    @echo "Cleaning up..."
    if exist "$(STAGE1_BIN)" del "$(STAGE1_BIN)"
    if exist "$(STAGE2_BIN)" del "$(STAGE2_BIN)"
    if exist "$(IMG)" del "$(IMG)"

问题原因及修复方案

1. 加载地址与跳转地址不匹配(核心错误)

Stage1中,你设置ES=0x7C0、BX=0x8000,对应物理加载地址为:
0x7C0 * 16 + 0x8000 = 0x7C00 + 0x8000 = 0xFC00

但跳转地址0x0800:0x0000对应的物理地址是:
0x0800 * 16 + 0x0000 = 0x8000

两个地址完全不匹配,导致跳转后执行的是空白内存,而非Stage2代码。

修复:修改Stage1的磁盘加载段寄存器配置,让加载地址与跳转地址一致:

mov ax, 0x0800      ; 段地址设为0x0800,对应物理地址0x8000
mov es, ax
mov bx, 0x0000      ; 偏移设为0,ES:BX指向0x8000

2. 代码注释与实际值不符

  • mov al, 01h注释写“读63扇区”,但实际只读取1扇区,修正注释避免混淆;
  • mov ch, 00h注释写“柱面1”,但实际是柱面0,修正注释。

3. Stage2冗余的引导扇区填充

Stage2不是BIOS需要识别的引导扇区,不需要TIMES 510-($-$$) db 0和DW 0xAA55,删除这些冗余代码。

4. 可选优化:增加错误提示

当前磁盘读错误直接调用int 18h,可以添加错误字符串打印逻辑,方便调试:

disk_read_error:
    mov si, error_msg
    call print_string  ; 需要实现类似Stage2的print_string函数
    int 18h

error_msg db "Disk read failed!", 0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:07:05