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

自定义OS内核加载失败问题求助

自定义内核加载失败,触发SIGSEGV段错误

开发自定义操作系统内核时,内核无法正常加载,无预期输出,使用gdb调试时出现以下错误:

During startup program terminated with signal SIGSEGV, Segmentation fault.

当前代码暂未规范整理,先聚焦解决加载问题,相关代码如下:

kernel/main.cpp

extern "C" void kernelMain() {
    const char* welcome = "Welcome to the kernel!";
    char* videoMemory = (char*) 0xb8000;

    for (int i = 0; i < 80*25; i++) {
        videoMemory[i*2] = ' ';
        videoMemory[i*2+1] = 0x0f;
    }

    for (int i = 0; welcome[i] != '\0'; i++) {
        videoMemory[i*2] = welcome[i];
    }
}

extern "C" void _start() {
    kernelMain();
    while (1) {}
}

kernel/linker.ld

ENTRY(_start)

SECTIONS
{
    . = 0x1000;
    .text : { *(.text) }
    .data : { *(.data) }
    .bss  : { *(.bss)  }
}

boot/boot.asm

[org 0x7c00]

start:
    mov si, msg
    call print

    mov ah, 0x02
    mov al, 0x06
    mov ch, 0x00
    mov cl, 0x02
    mov dh, 0x00
    mov dl, 0x80
    mov bx, 0x1000
    int 0x13

    jmp 0x1000

print:
    mov ah, 0x0e
    mov bh, 0x00
    mov bl, 0x07
    mov al, [si]
    cmp al, 0
    je .done
    int 0x10
    inc si
    jmp print

.done:
    ret

msg db "Loading Bootloader...", 0

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

Makefile

NASM=nasm
QEMU=qemu-system-x86_64
CC=gcc
LD=ld

all: boot.bin kernel.bin

boot.bin: boot/boot.asm
    $(NASM) -f bin $< -o $@

kernel.bin: kernel/main.cpp kernel/linker.ld
    $(CC) -ffreestanding -c $< -o kernel.o
    $(LD) -o $@ -T kernel/linker.ld kernel.o

run: boot.bin kernel.bin
    $(QEMU) -drive format=raw,file=boot.bin

clean:
    rm -f boot.bin kernel.bin kernel.o

问题分析与修复步骤

1. 核心问题:内核未写入磁盘镜像

原Makefile的run命令仅加载boot.bin,内核kernel.bin并未合并到QEMU使用的磁盘镜像中。引导扇区执行读盘操作时,实际读取的是无效数据,跳转到0x1000后执行垃圾代码触发段错误。

修复Makefile:生成包含引导扇区和内核的完整磁盘镜像:

run: boot.bin kernel.bin
    # 创建100扇区的空镜像
    dd if=/dev/zero of=os.img bs=512 count=100
    # 写入引导扇区到第一个扇区
    dd if=boot.bin of=os.img conv=notrunc
    # 从第2个扇区开始写入内核(对应引导扇区cl=0x02的设置)
    dd if=kernel.bin of=os.img bs=512 seek=1 conv=notrunc
    # 运行完整镜像
    $(QEMU) -drive format=raw,file=os.img

2. 编译参数错误:默认生成64位代码

GCC默认编译64位代码,但引导扇区运行在16位实模式,跳转到0x1000后执行64位指令会导致错误。需指定32位编译和链接参数。

修复编译与链接命令:

kernel.bin: kernel/main.cpp kernel/linker.ld
    # 32位独立环境编译,禁用标准库、异常、RTTI
    $(CC) -ffreestanding -m32 -nostdlib -fno-exceptions -fno-rtti -c $< -o kernel.o
    # 32位ELF链接
    $(LD) -m elf_i386 -o $@ -T kernel/linker.ld kernel.o

3. 缺失读盘错误检查

引导扇区的int 0x13读盘操作未检查错误标志,读盘失败时会直接跳转,导致后续执行无效代码。

修复引导扇区:添加读盘错误处理:

[org 0x7c00]

start:
    mov si, msg
    call print

    mov ah, 0x02
    mov al, 0x06
    mov ch, 0x00
    mov cl, 0x02
    mov dh, 0x00
    mov dl, 0x80
    mov bx, 0x1000
    int 0x13
    jc disk_error  ; CF置位表示读盘失败,跳转错误处理

    jmp 0x1000

disk_error:
    mov si, disk_err_msg
    call print
    hlt  ; 暂停系统,避免继续执行错误代码

print:
    mov ah, 0x0e
    mov bh, 0x00
    mov bl, 0x07
    mov al, [si]
    cmp al, 0
    je .done
    int 0x10
    inc si
    jmp print

.done:
    ret

msg db "Loading Bootloader...", 0
disk_err_msg db "Disk read error!", 0

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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 00:15:05