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

Bootloader跳转Kernel失败求助(已进入Protected Mode,附代码)

Bootloader跳转至Kernel失败问题排查与解决

核心问题定位

跳转失败、QEMU陷入循环的问题,大概率源于以下几个关键点:

  • 内核代码的编译链接地址与加载地址不匹配
  • 磁盘加载的内核内容无效
  • 内核入口点未适配32位保护模式

具体排查与修复步骤

1. 确保内核编译链接地址与加载地址一致

你将内核加载到物理地址0x8000,因此内核必须以该地址为基址编译:

  • 内核汇编开头需声明bits 32和org 0x8000
  • 链接时指定入口地址,例如用GNU ld:ld -m elf_i386 -Ttext 0x8000 -o kernel.elf kernel.o

示例32位内核代码(kernel.asm):

bits 32
org 0x8000

kernel_start:
    ; 往VGA显存写字符,确认内核正常运行
    mov byte [0xB8000 + 2], 'K'
    mov byte [0xB8000 + 3], 0x0F

    cli
    hlt
    jmp $

2. 验证磁盘加载的内核有效性

在Bootloader的32位模式代码中,跳转前添加检查逻辑,确认内核已正确加载到0x8000:

[bits 32]
protected_mode:
    ; ... 原有段寄存器、栈设置代码 ...

    mov byte [0xB8000], 'P'
    mov byte [0xB8001], 0x0e

    ; 检查内核开头的签名(可在内核代码开头定义0xDEADBEEF)
    cmp dword [0x8000], 0xDEADBEEF
    jne kernel_load_fail

    ; 执行跳转
    jmp 0x08:KERNEL

kernel_load_fail:
    mov byte [0xB8000 + 4], 'E'
    mov byte [0xB8000 + 5], 0x0C
    cli
    hlt

3. 确认跳转指令与模式切换正确性

你的jmp 0x08:KERNEL指令本身是正确的(0x08对应GDT中基址0、限长4GB的代码段选择子),需确保:

  • 模式切换完成:jmp 0x08:protected_mode已完成16位到32位保护模式的切换,这部分代码无问题
  • 栈指针安全:esp=0x90000避开了Bootloader和内核的内存区域,设置合理

4. 额外注意事项

  • 中断控制:跳转前已执行cli,避免中断干扰模式切换与内核运行
  • A20线:你用的0x92端口快速启用方法在QEMU中有效,若后续适配真实硬件,建议改用键盘控制器兼容方法
  • 磁盘参数:rdisk函数中dl=0x80对应第一块硬盘,QEMU环境下参数正确

完整修改后的Bootloader跳转代码段

[bits 32]
protected_mode:
    cli
    mov eax, 0x10
    mov ds, eax
    mov es, eax
    mov ss, eax
    mov fs, eax
    mov gs, eax
    mov ebp, 0x90000
    mov esp, ebp

    mov byte [0xB8000], 'P'
    mov byte [0xB8001], 0x0e

    ; 验证内核加载状态(可选)
    cmp dword [KERNEL], 0xDEADBEEF
    jne .load_err

    ; 跳转到内核入口
    jmp 0x08:KERNEL

.load_err:
    mov byte [0xB8000 + 2], 'E'
    mov byte [0xB8000 + 3], 0x0C
    cli
    hlt
    jmp $

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.07 16:14:50