自制操作系统内核无法输出字符至屏幕,求助故障排查
内核无法打印字符的问题排查与修复
我开发的操作系统无法向屏幕输出字符,内核无法打印字符。编译运行后系统能被识别启动,但屏幕无任何内容,调整编译脚本后问题仍存在。相关代码如下:
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
问题修复要点
内核加载扇区数不足
bootloader中仅加载1个扇区(mov al, 1),但编译后的kernel.bin大小大概率超过512字节,导致内核代码未完全加载到内存。修改为加载足够多的扇区,比如:mov al, 5 ; 加载5个扇区,可根据实际kernel.bin大小调整G++编译参数缺失
未指定32位架构,默认可能生成64位代码,实模式下无法执行。修改编译命令:g++ -ffreestanding -m32 -c -o kernel.o kernel.cpp链接器参数错误
未指定32位x86架构,也未明确内核入口函数为kernelMain,导致链接后的代码入口偏移错误。修改链接命令:ld -m i386elf -Ttext 0x1000 -e kernelMain -o kernel.elf kernel.o可选:添加磁盘错误提示
在disk_error标签处添加屏幕输出,方便排查加载失败问题:disk_error: mov ah, 0x0E mov al, 'E' int 0x10 hlt
完成以上修改后,重新编译运行即可看到内核输出的"Hello, OS!"。
内容的提问来源于stack exchange,提问作者bessieTheBoy
相关产品推荐
相关产品推荐

