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

在QEMU中运行简易Bootloader与虚拟内核仅输出$的问题求助

问题:Bootloader加载内核后仅输出$符号,无法执行内核代码

编译启动过程无报错,仅QEMU提示probing guessed raw警告,但最终仅显示$符号,内核的!未输出。

现有代码

Bootloader代码(boot.asm)

[org 0x7c00]
[bits 16]

bt:
    mov ax, 0x0201
    mov bx, 0x1000
    mov cx, 0x0002
    mov dx, 0x0000
    mov es, bx
    int 0x13
    jc  dsk_err
    mov ax, 0x0e24 ;print '$'
    mov bh, 0
    int 0x10
    jmp 0x1000:0x00

dsk_err:
    mov ax, 0x0e21 ;print '!'
    mov bh, 0
    int 0x10
    hlt

times 510-($-$$) db 0
dw 0xaa55

内核代码(kernel.asm)

[org 0]
[bits 16]

section .text
    global _start

_start:
    mov ax, 0x0e21 ;print '!' to make sure it works
    mov bh, 0
    int 0x10
    hlt

times 510-($-$$) db 0
dw 0xaa55

分隔文件zero.bin

由以下代码编译生成:

times 0x1000-512 db 0

镜像制作命令:

cat boot.bin zero.bin kernel.bin > disk.img

问题分析

  1. 缓冲区地址错误:
    int 0x13(读磁盘扇区)将数据写入ES:BX指向的内存地址。现有代码中mov bx, 0x1000后又mov es, bx,导致ES=0x1000、BX=0x1000,实际写入地址为0x1000*16 + 0x1000 = 0x11000,但后续跳转的是0x1000:0x00(即物理地址0x10000),两者不匹配,跳转到了无有效代码的区域。

  2. 扇区编号错误:
    zero.bin大小为0x1000-512=3584字节,对应3584/512=7个磁盘扇区。Bootloader占第1扇区,zero.bin占第2-8扇区,内核实际在第9扇区。现有代码中cx=0x0002读取的是第2扇区(zero.bin的起始部分),而非内核所在扇区。

修正方案

修改后的Bootloader代码

[org 0x7c00]
[bits 16]

bt:
    mov ax, 0x0201       ; AH=02h(读扇区),AL=1(读1个扇区)
    mov bx, 0x0000       ; BX=0,作为缓冲区偏移
    mov cx, 0x0009       ; CH=0(柱面号低8位),CL=09h(扇区9,柱面号高2位为0)
    mov dx, 0x0000       ; DL=0(软盘驱动器),DH=0(磁头0)
    mov es, 0x1000       ; ES=0x1000,缓冲区段地址
    int 0x13
    jc  dsk_err
    mov ax, 0x0e24       ; 输出$
    mov bh, 0
    int 0x10
    jmp 0x1000:0x00      ; 跳转到内核入口(0x1000:0x00 = 0x10000)

dsk_err:
    mov ax, 0x0e21       ; 输出!表示读盘错误
    mov bh, 0
    int 0x10
    hlt

times 510-($-$$) db 0
dw 0xaa55

验证步骤

  1. 重新编译各文件:
    nasm -f bin boot.asm -o boot.bin
    nasm -f bin kernel.asm -o kernel.bin
    nasm -f bin zero.asm -o zero.bin
    
  2. 重新生成镜像:
    cat boot.bin zero.bin kernel.bin > disk.img
    
  3. 启动QEMU:
    qemu-system-i386 -fda disk.img
    

此时应该能看到先输出$,随后输出!,表示内核成功执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 09:02:11