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

自制操作系统内核无法输出字符至屏幕,求助故障排查

内核无法打印字符的问题排查与修复

我开发的操作系统无法向屏幕输出字符,内核无法打印字符。编译运行后系统能被识别启动,但屏幕无任何内容,调整编译脚本后问题仍存在。相关代码如下:

boot.asm

global _start

section .text
_start:
    ; Set up the stack
    mov esp, 0x90000

    ; Load the kernel
    mov ah, 0x02 ; BIOS read sector function
    mov al, 1    ; Number of sectors to read
    mov ch, 0    ; Cylinder number
    mov dh, 0    ; Head number
    mov dl, 0x80 ; Drive number (0x80 for the first hard drive)
    mov bx, 0x1000 ; Load to address 0x1000 (where we'll jump to)

    int 0x13     ; BIOS interrupt: read sectors into memory
    jc disk_error ; Jump if carry flag set (error)

    ; Jump to the kernel
    jmp 0x1000

disk_error:
    ; Handle disk error here (you can add more code)
    hlt

times 510 - ($ - $$) db 0
dw 0xAA55 ; Boot signature

kernel.cpp

extern "C" void kernelMain() {
    ; Pointer to the video memory (text mode buffer)
    char* videoMemory = (char*)0xB8000;

    ; Message to be displayed
    const char* message = "Hello, OS!";

    ; Set the attribute byte (white on black)
    char attributeByte = 0x07;

    ; Loop to print the message to the screen
    for (int i = 0; message[i] != '\0'; i++) {
        ; Calculate the memory offset
        int offset = i * 2;

        ; Set the character and attribute in video memory
        videoMemory[offset] = message[i];
        videoMemory[offset + 1] = attributeByte;
    }

    ; Infinite loop to halt the CPU
    while (1) {
        asm("hlt");
    }
}

compile.bat

@echo off
REM Compile the kernel source code (kernel.cpp)
g++ -ffreestanding -c -o kernel.o kernel.cpp

REM Link the kernel object file and set the entry point at 0x1000
ld -Ttext 0x1000 -o kernel.elf kernel.o

REM Convert the ELF kernel binary to a flat binary
objcopy -O binary kernel.elf kernel.bin

REM Assemble the bootloader (boot.asm) to produce boot.bin
nasm -f bin -o boot.bin boot.asm

REM Concatenate the bootloader and kernel into os.img
powershell -Command "[System.IO.File]::WriteAllBytes('os.img', [System.IO.File]::ReadAllBytes('boot.bin') + [System.IO.File]::ReadAllBytes('kernel.bin'))"

REM Run the OS using QEMU
qemu-system-i386 -fda os.img

问题修复要点

  1. 内核加载扇区数不足
    bootloader中仅加载1个扇区(mov al, 1),但编译后的kernel.bin大小大概率超过512字节,导致内核代码未完全加载到内存。修改为加载足够多的扇区,比如:

    mov al, 5    ; 加载5个扇区,可根据实际kernel.bin大小调整
    
  2. G++编译参数缺失
    未指定32位架构,默认可能生成64位代码,实模式下无法执行。修改编译命令:

    g++ -ffreestanding -m32 -c -o kernel.o kernel.cpp
    
  3. 链接器参数错误
    未指定32位x86架构,也未明确内核入口函数为kernelMain,导致链接后的代码入口偏移错误。修改链接命令:

    ld -m i386elf -Ttext 0x1000 -e kernelMain -o kernel.elf kernel.o
    
  4. 可选:添加磁盘错误提示
    在disk_error标签处添加屏幕输出,方便排查加载失败问题:

    disk_error:
        mov ah, 0x0E
        mov al, 'E'
        int 0x10
        hlt
    

完成以上修改后,重新编译运行即可看到内核输出的"Hello, OS!"。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 03:35:31