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

使用自定义Bootloader与Kernel时VirtualBox触发Guru Meditation求排查

问题排查:VirtualBox Guru Meditation 触发原因及修复

核心问题分析

你的代码存在两个致命错误,直接导致VirtualBox崩溃:

  1. 保护模式下调用BIOS中断:在32位保护模式的init_pm代码块中,你调用了BIOS磁盘中断int 0x13。BIOS中断仅在16位实模式下有效,保护模式下中断向量表结构、特权级规则完全不同,强行调用会触发非法操作,这是Guru Meditation的主要诱因。
  2. 磁盘读取逻辑冗余且错误:你先在保护模式读盘到0x7E00,再复制到0x10000,完全没必要,且读盘操作本身就不应该在保护模式执行。

修复后的Bootloader代码(boot.asm)

[org 0x7C00]                ; 设置加载基址为0x7C00

; --- 实模式初始化 ---
mov bp, 0x9000              ; 设置栈基址
mov sp, bp                  ; 初始化栈指针

; --- 实模式下读取Kernel到内存 ---
; 将Kernel读取到0x10000位置(无需后续复制)
mov bx, 0x1000              ; ES:BX = 0x0000:0x1000 = 0x10000
mov dh, 1                   ; 读取1个扇区
mov dl, 0x80                ; 从第一块硬盘读取
mov ah, 0x02                ; BIOS读扇区功能
mov al, dh                  ; 读取的扇区数
mov ch, 0                   ; 磁道号0
mov cl, 2                   ; 起始扇区2
mov dh, 0                   ; 磁头0
int 0x13                    ; 调用BIOS中断
jc disk_error               ; 读盘失败则跳转错误处理

; --- 设置GDT并进入保护模式 ---
cli                         ; 关闭中断
lgdt [gdt_descriptor]       ; 加载GDT描述符

mov eax, cr0
or eax, 0x1                 ; 设置PE位开启保护模式
mov cr0, eax

jmp 0x08:init_pm            ; 长跳转到保护模式代码(刷新指令流水线)

[bits 32]
init_pm:
    ; 初始化段寄存器(使用GDT的数据段选择子0x10)
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    mov esp, 0x90000        ; 设置保护模式栈指针(更高的安全地址)

    jmp 0x08:0x10000        ; 跳转到Kernel入口

disk_error:
    hlt
    jmp disk_error          ; 无限循环处理错误

[bits 16]
; --- GDT定义 ---
GDT:
    ; 空描述符
    dd 0x0
    dd 0x0

    ; 32位代码段描述符
    dw 0xffff               ; 段限长低16位
    dw 0x0                  ; 段基址低16位
    db 0x0                  ; 段基址中8位
    db 0b10011010           ; 类型:可执行、可读、非特权级
    db 0b11001111           ; 粒度:4KB,段限长高4位
    db 0x0                  ; 段基址高8位

    ; 32位数据段描述符
    dw 0xffff
    dw 0x0
    db 0x0
    db 0b10010010           ; 类型:可读可写、非特权级
    db 0b11001111
    db 0x0

gdt_descriptor:
    dw $ - GDT - 1          ; GDT长度(减1)
    dd GDT                  ; GDT基地址

; --- 引导扇区填充 ---
times 510 - ($ - $$) db 0
dw 0xAA55                  ; 引导签名

Kernel编译与链接注意事项

确保你的Kernel被编译为32位无依赖的二进制文件,使用以下命令:

  1. 编译Kernel:
gcc -m32 -ffreestanding -c kernel.c -o kernel.o
  1. 链接到指定地址0x10000:
ld -m elf_i386 -Ttext 0x10000 --oformat binary kernel.o -o kernel.bin
  1. 制作启动盘镜像:
cat boot.bin kernel.bin > os.img

其他注意点

  • VirtualBox中选择启动盘为os.img,并确保虚拟机设置为"Legacy BIOS"模式(UEFI模式不兼容MBR引导)。
  • 你的Kernel代码本身没有问题,只要能正确跳转到_start入口,就能正常输出字符串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 21:19:55