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

Bootloader在QEMU正常运行,真机无法跳转至内核求助

真机启动OS时Bootloader跳转内核失败及硬盘启动异常问题

近几周我一直在开发一款OS,前期进展顺利,但尝试在真机运行时,Bootloader无法跳转到内核。我尝试用硬盘替代U盘启动,结果连Bootloader都无法加载,而U盘能正常识别Bootloader。我已查阅资料、更换过相关代码,但仍无法解决内核跳转问题。

Bootloader代码

[ORG 0x7c00]

[BITS 16]

CODE_SEG EQU gdt_code - gdt_start
DATA_SEG EQU gdt_data - gdt_start

jmp short biosBlock  
nop

biosBlock:
    jmp 0:start

start:
    ; 一些检查操作
    cli ; 关闭中断
    mov ax, 0x00
    mov ds, ax
    mov es, ax

    mov ss, ax
    mov sp, 0x7c00
    sti ; 开启中断

.load_protected:
    cli
    lgdt[gdt_descriptor]
    mov eax, cr0
    or eax, 0x1
    mov cr0, eax
    jmp CODE_SEG:load32

; 配置GDT以支持4GB内存访问
gdt_start:
gdt_nul:
    dd 0x0
    dd 0x0

; 偏移量0x8
gdt_code:  ; cs寄存器需指向该段
    dw 0xffff
    dw 0
    db 0
    db 0x9a
    db 11001111b
    db 0
; 偏移量0x10
gdt_data:
    dw 0xffff
    dw 0
    db 0
    db 0x92
    db 11001111b
    db 0

gdt_end:

gdt_descriptor:
    dw gdt_end - gdt_start - 1
    dd gdt_start

[BITS 32]
load32:
    mov eax, 1
    mov ecx, 100
    mov edi, 0x0100000
    call ata_lba_read
    jmp CODE_SEG:0x0100000

ata_lba_read:
    mov ebx, eax ; 备份LBA地址
    ; 向硬盘控制器发送LBA地址的最高8位
    shr eax, 24
    or eax, 0xE0 ; 选择主驱动器
    mov dx, 0x1F6
    out dx, al
    ; 完成LBA最高8位发送

    ; 发送要读取的总扇区数
    mov eax, ecx
    mov dx, 0x1F2
    out dx, al
    ; 完成总扇区数发送

    ; 发送LBA地址的低8位
    mov eax, ebx ; 恢复备份的LBA地址
    mov dx, 0x1F3
    out dx, al
    ; 完成LBA低8位发送

    ; 发送LBA地址的中8位
    mov dx, 0x1F4
    mov eax, ebx ; 恢复备份的LBA地址
    shr eax, 8
    out dx, al
    ; 完成LBA中8位发送

    ; 发送LBA地址的高16位
    mov dx, 0x1F5
    mov eax, ebx ; 恢复备份的LBA地址
    shr eax, 16
    out dx, al
    ; 完成LBA高16位发送

    mov dx, 0x1f7
    mov al, 0x20
    out dx, al 

.next_sector:
    push ecx

.try_again:
    mov dx, 0x1f7
    in al, dx
    test al, 8
    jz .try_again

; 每次读取256个字
    mov ecx, 256
    mov dx, 0x1F0
    rep insw
    pop ecx
    loop .next_sector
    ; 完成扇区读取并写入内存
    ret

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

Makefile代码

dd if=./bin/boot.bin >> ./bin/os.bin
dd if=./bin/kernel.bin >> ./bin/os.bin
dd if=/dev/zero bs=1048576 count=32 >> ./bin/os.bin

写入U盘的命令

dd if=os.bin of="the_usb"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 23:05:27