为何自定义内核在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ć
相关产品推荐
相关产品推荐

