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

为什么自制操作系统在QEMU中无法启动,仅在光标前显示空格?

故障根因与修复方案

第一类致命错误:引导扇区基础配置错误

  • org地址偏移错误:你写的[org 7c000h]是完全错误的,BIOS会将合法引导扇区加载到物理地址0x7c00,多写了一个0导致所有代码地址偏移全部错位,CPU执行指令完全混乱,这是Bochs卡住的核心原因。
  • 打印函数逻辑错误:print_str.asm中的_print仅能打印单个字符,没有循环遍历字符串直到结束符\0的逻辑,所以你看不到任何完整的提示字符串输出。
  • 引导盘号未正确保存:BIOS启动时会将引导设备的盘号存入dl寄存器,你没有在代码最开头将dl的值写入DRIVE_ID变量,直接读取初始值为0的DRIVE_ID大概率会导致磁盘读操作失败。
  • 磁盘读参数完全错误
    1. 你要读取的内核位于引导扇区之后,对应物理扇区号为2,你设置cl=1会重读引导扇区本身,根本读不到内核
    2. 你设置es=KERNEL_HEX=0x1000,bx=0,所以内核加载到的物理地址是0x1000*16 + 0 = 0x10000,不是0x1000,你在保护模式下直接call KERNEL_HEX调用的是0x1000地址的随机数据,根本不是内核代码。

第二类致命错误:编译流程完全错误

  • 你生成的最终镜像osimg没有包含boot.bin引导扇区,而是直接拼接了link.o和krnl.o两个ELF格式的目标文件,根本不是可执行的二进制镜像,QEMU找不到合法引导签名0xAA55自然会报boot device not found。
  • 你ld命令生成的krnlf.bin是已经链接好的纯二进制内核文件,完全没有被用到,拼接ELF目标文件的操作没有任何意义。
  • 内核代码的显存操作错误:32位文本模式下每个字符占2字节,低字节是ASCII码,高字节是颜色属性,你只写了ASCII码,高字节属性为随机值大概率是0,即黑底黑字,所以你看不到S的显示,只会看到随机的空格或者无显示。

修复步骤

  1. 将[org 7c000h]改为[org 0x7c00]
  2. 修正print_str.asm,添加字符串循环遍历逻辑,直到遇到\0结束打印
  3. 在引导代码最开头添加mov [DRIVE_ID], dl,保存BIOS传入的引导盘号
  4. 磁盘读操作设置cl=2,读取引导扇区之后的内核扇区,保护模式下调用内核改为call 0x10000
  5. 修正内核代码的显存写入逻辑:
#include <stdint.h>
void main(void) {
    uint16_t *VID_MEM = (uint16_t *) 0xB8000;
    *VID_MEM = 'S' | (0x0F << 8); // 0x0F是白字黑底属性
}
  1. 修正编译流程:
nasm link.asm -f elf32 -o link.o
nasm start_boot.asm -f bin -o boot.bin
gcc -m32 -ffreestanding -c kernel.c -o krnl.o
ld -m elf_i386 -o krnlf.bin -Ttext 0x10000 link.o krnl.o --oformat binary
cat boot.bin krnlf.bin > osimg
# 给osimg补全大小到至少1.44M适配软盘镜像:
dd if=/dev/zero of=osimg bs=1M count=1 conv=notrunc
  1. 如果你用的是64位编译器,编译32位代码需要加-m32参数,避免64位和32位目标文件不兼容的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 16:57:01