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

为何自定义内核在QEMU中正常运行,裸机环境启动却崩溃?

内核启动异常排查:QEMU正常,裸机Ventoy引导崩溃

问题描述

  • 内核初始版本在QEMU中通过自制ISO运行正常,但裸机用Ventoy引导该ISO时,会在mov cr0, eax指令或下一条指令处崩溃
  • 内核加载地址为0x7E00,尝试加载到更高地址会触发链接器截断问题
  • 怀疑扇区加载数量不足:加载超过6个扇区时代码完全无法运行;加载6个或更少扇区时,会在固定位置崩溃
  • 使用int 0x13, ah=0x42从ISO加载扇区,启动流程:512字节引导程序 → arch程序 → 内核

相关代码

引导程序代码(boot.asm)

bits 16
org 0x7C00

cli

mov [boot_drive], dl

mov si, dap
mov ah, 0x42
mov dl, [boot_drive]
int 0x13

jmp 0x0000:0x7E00

boot_drive db 0

; disk address packet

align 16
dap:
    db 0x10            ; size of DAP
    db 0x00            ; reserved
    dw 6               ; number of sectors to read
    dw 0x7E00          ; buffer offset
    dw 0x0000          ; buffer segment
    dd 24              ; lower 32 bits of LBA
    dw 0x0000          ; upper 16 bits of LBA
    db 0x00            ; reserved
    db 0x00            ; reserved

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

架构过渡代码(arch.asm)

BITS 16

global _start
global PMT
global PDPT
global PD
global PT
global entry_count

extern main
extern map_start

section .text

_start:

mov ax, 0x0003
int 0x10

mov ah, 0x0E
mov al, 'A'
int 0x10

; Get RAM

mov ebx, 0                  ; Continuation value
mov bp, 0                   ; Counter
mov ax, map_start
shr ax, 4
mov es, ax                  ; Return memory
mov di, 0                   ; Offset

.next_entry:
    mov eax, 0xE820         ; Get memory map
    mov ecx, 24             ; map_start size
    mov edx, 0x534D4150     ; 'SMAP' - Handshake
    int 0x15

    inc bp
    add di, 24

    test ebx, ebx
    jnz .next_entry

    mov eax, ebp
    mov [entry_count], eax

; Transition

lgdt [gdt_descriptor]

mov eax, cr0
or eax, CR0_PE  ; protection enable
mov cr0, eax

jmp gdt_table_32.code_32:pm_start

; protected mode

bits 32
pm_start:
    mov ax, gdt_table_32.data_32
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax


lgdt [gdt_descriptor_64]

; Page init

mov eax, PDPT
or eax, 0b100001011
mov [PMT], eax

; Virtual 1 GiB entry
mov eax, PD
or eax, 0b100001011
mov [PDPT], eax

; 2 MiB physical entries

mov eax, 0x0         ; Following 1 GiB
or eax, 0b110001011
mov [PD], eax

; long mode transition

mov eax, cr4
or eax, CR4_PAE     ; physical address extension
mov cr4, eax

mov eax, PMT    ; paging structure address
mov cr3, eax

mov ecx, 0xC0000080     ; IA32_EFER
rdmsr
or eax, 1 << 8
wrmsr

mov eax, cr0
or eax, CR0_PG      ; enable paging
mov cr0, eax

jmp gdt_table_64.code_64:lm_start

; long mode

bits 64
lm_start:
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    mov rsp, stack_top

kernel_entry:
    call main
jmp kernel_entry


section .data

; control registers

CR0_PE equ 1
CR0_PG equ 1 << 31
CR4_PAE equ 1 << 5

entry_count:
    dd 0

; gdt

align 8
gdt_table_32:
    dq 0x0000000000000000

    .data_32: equ $ - gdt_table_32
        dw 0xFFFF       ; limit
        dw 0            ; base
        db 0            ; base
        db 10010010b    ; present, dpl, seg type[4], desc t
        db 11011111b    ; G, 16/32, long, system use, limit[4]
        db 0            ; base

    .code_32: equ $ - gdt_table_32
        dw 0xFFFF
        dw 0
        db 0
        db 10011010b
        db 11011111b
        db 0
gdt_table_32_end:

align 4
gdt_descriptor:
    dw gdt_table_32_end - gdt_table_32 - 1
    dd gdt_table_32

align 8
gdt_table_64:
    dq 0x0000000000000000

    .code_64: equ $ - gdt_table_64
        dw 0xFFFF
        dw 0
        db 0
        db 10011010b
        db 10111111b
        db 0
gdt_table_64_end:

align 4
gdt_descriptor_64:
    dw gdt_table_64_end - gdt_table_64 - 1
    dq gdt_table_64


section .bss

; stack

align 16
stack_bottom:
    resb 4096
stack_top:

; page table structure

align 4096
PMT:
    resb 4096
PDPT:
    resb 4096
PD:
    resb 4096
PT:
    resb 4096

构建命令

nasm -f bin src/boot/boot.asm -o bin/boot.bin
nasm -f elf64 src/boot/arch.asm -o obj/arch.o
nasm -f elf64 src/memory/order_list.asm -o obj/order_list.o
nasm -f elf64 src/memory/mem_copy.asm -o obj/mem_copy.o
nasm -f elf64 src/display/disable_cursor.asm -o obj/disable_cursor.o
nasm -f elf64 src/ints/apic_util.asm -o obj/apic_util.o
nasm -f elf64 src/ints/lvt_util.asm -o obj/lvt_util.o

x86_64-elf-gcc -ffreestanding -m64 -masm=intel -Iinclude -c src/kernel.c -o obj/kernel.o
x86_64-elf-gcc -ffreestanding -m64 -masm=intel -Iinclude -c src/memory/virtual.c -o obj/virtual.o
x86_64-elf-gcc -ffreestanding -m64 -masm=intel -Iinclude -c src/memory/physical.c -o obj/physical.o
x86_64-elf-gcc -ffreestanding -m64 -masm=intel -Iinclude -c src/display/print.c -o obj/print.o
x86_64-elf-gcc -ffreestanding -m64 -masm=intel -Iinclude -c src/ints/exceptions.c -o obj/exceptions.o
x86_64-elf-gcc -ffreestanding -m64 -masm=intel -Iinclude -c src/ints/x2APIC.c -o obj/x2APIC.o

x86_64-elf-ld -T linker.ld -o obj/kernel.elf obj/arch.o obj/virtual.o obj/physical.o obj/order_list.o obj/print.o obj/mem_copy.o obj/disable_cursor.o obj/exceptions.o obj/x2APIC.o obj/apic_util.o obj/lvt_util.o obj/kernel.o

x86_64-elf-objcopy -O binary obj/kernel.elf bin/kernel.bin

cat bin/boot.bin bin/kernel.bin > bin/kernel.img
nasm -f bin src/boot/boot.asm -o bin/boot.bin
nasm -f elf64 src/boot/arch.asm -o obj/arch.o
nasm -f elf64 src/memory/order_list.asm -o obj/order_list.o
nasm -f elf64 src/memory/mem_copy.asm -o obj/mem_copy.o
nasm -f elf64 src/display/disable_cursor.asm -o obj/disable_cursor.o
nasm -f elf64 src/ints/apic_util.asm -o obj/apic_util.o
nasm -f elf64 src/ints/lvt_util.asm -o obj/lvt_util.o

x86_64-elf-gcc -ffreestanding -m64 -masm=intel -Iinclude -c src/kernel.c -o obj/kernel.o
x86_64-elf-gcc -ffreestanding -m64 -masm=intel -Iinclude -c src/memory/virtual.c -o obj/virtual.o
x86_64-elf-gcc -ffreestanding -m64 -masm=intel -Iinclude -c src/memory/physical.c -o obj/physical.o
x86_64-elf-gcc -ffreestanding -m64 -masm=intel -Iinclude -c src/display/print.c -o obj/print.o
x86_64-elf-gcc -ffreestanding -m64 -masm=intel -Iinclude -c src/ints/exceptions.c -o obj/exceptions.o
x86_64-elf-gcc -ffreestanding -m64 -masm=intel -Iinclude -c src/ints/x2APIC.c -o obj/x2APIC.o

x86_64-elf-ld -T linker.ld -o obj/kernel.elf obj/arch.o obj/virtual.o obj/physical.o obj/order_list.o obj/print.o obj/mem_copy.o obj/disable_cursor.o obj/exceptions.o obj/x2APIC.o obj/apic_util.o obj/lvt_util.o obj/kernel.o

x86_64-elf-objcopy -O binary obj/kernel.elf bin/kernel.bin

cat bin/boot.bin bin/kernel.bin > bin/kernel.img

内容的提问来源于stack exchange,提问作者Adi Mehmedičević

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 21:09:51