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

自制汇编操作系统在Qemu中启动失败,无法显示Hello World

问题分析与修复方案

核心问题拆解

你的代码出现boot failed且无输出,主要源于三个关键错误:引导扇区格式无效、内核加载/链接地址不匹配、缺少磁盘操作错误处理。以下是具体修复步骤:


1. 修复引导扇区编译格式

引导扇区是实模式下直接运行的512字节二进制代码,不能用ELF格式编译(-f elf32)——ELF目标文件包含额外头信息,会导致times 510-($-$$)的填充计算错误,最终生成的文件末尾没有正确的0xAA55引导标志,QEMU无法识别为可引导软盘。

修正后的bootloader.asm

section .text
org 0x7c00  ; 告诉nasm代码将被加载到0x7c00地址执行

_start:
    cli
        
    xor ax, ax
    mov ds, ax
    mov es, ax
        
    mov ss, ax
    mov sp, 0x9000

    ; 读取磁盘:将第2个扇区加载到0x8000
    mov bx, 0x8000
    mov dh, 0   ; 磁头0
    mov dl, 0   ; 驱动器0(软盘)
    mov ch, 0   ; 柱面0
    mov cl, 2   ; 扇区2
    mov ah, 2   ; 读扇区功能
    mov al, 1   ; 读取1个扇区
    int 0x13    

    ; 检查磁盘读取错误(CF置位表示失败)
    jc disk_error

    jmp 0x8000

disk_error:
    ; 输出错误提示
    mov ah, 0x0E
    mov al, 'E'
    int 0x10
    hlt

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

关键修改:

  • 添加org 0x7c00,让nasm正确计算指令地址
  • 明确指定读取1个扇区(mov al,1)
  • 增加磁盘读取错误检查和处理

2. 匹配内核加载与链接地址

bootloader要把内核加载到0x8000,所以必须告诉nasm内核代码将在0x8000地址执行,否则跳转后指令地址不匹配,执行垃圾代码。

修正后的kernel.asm

section .text
org 0x8000  ; 指定代码加载到0x8000执行

_start_kernel:
    mov ah, 0x0E
    mov al, 'H'    
    int 0x10       
    
    mov al, 'e'
    int 0x10
    
    mov al, 'l'
    int 0x10
    
    mov al, 'l'
    int 0x10
    
    mov al, 'o'
    int 0x10

loop:
    hlt
    jmp loop  ; 防止hlt后被中断唤醒继续执行

times 512-($-$$) db 0

关键修改:

  • 添加org 0x8000
  • 增加死循环,避免hlt后CPU继续执行无效代码

3. 修复软盘镜像生成流程

原来的链接脚本把bootloader和kernel合并为ELF格式文件,破坏了引导扇区结构。正确做法是分别编译两者为二进制文件,再合并成软盘镜像(第一个扇区是bootloader,第二个是kernel)。

修正后的Makefile

boot = bootloader.asm
kernel = kernel.asm

boot_bin = bootloader.bin
kernel_bin = kernel.bin

os = os.bin

asm_compiler = nasm

compile:
    $(asm_compiler) -f bin $(boot) -o $(boot_bin)
    $(asm_compiler) -f bin $(kernel) -o $(kernel_bin)
    cat $(boot_bin) $(kernel_bin) > $(os)  ; 合并两个扇区为软盘镜像

run:
    qemu-system-i386 -fda $(os)

clean:
    rm $(boot_bin) $(kernel_bin) $(os)

关键修改:

  • 编译bootloader和kernel为纯二进制格式
  • 通过cat合并两个512字节文件,生成合法的软盘镜像

错误根源总结

  1. 引导扇区无效:ELF格式编译导致0xAA55标志位置错误,QEMU无法识别引导盘
  2. 地址不匹配:内核链接地址与bootloader加载地址不一致,跳转后执行错误代码
  3. 无错误处理:磁盘读取失败时直接跳转至无效地址,无法定位问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:53:32