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

自定义Bootloader与Kernel启动仅显示光标问题排查求助

自定义Bootloader+Kernel系统无输出问题排查指南

问题概述

开发的简易OS基于自定义Bootloader和汇编Kernel,启动后仅显示光标,无任何输出。已确认Bootloader将Kernel加载到指定内存,但调试输出无显示,需排查原因。

环境信息

  • Bootloader(bootloader.asm):汇编编写,负责加载Kernel到内存
  • Kernel(kernel.asm):汇编编写,包含初始化与UI交互逻辑
  • 工具链:NASM汇编、LD链接
  • 测试环境:物理硬件

已完成排查

  • 验证内存地址内容,确认Kernel已被Bootloader正确加载
  • 在Bootloader和Kernel中添加调试输出,无任何显示

代码片段

Bootloader代码

[BITS 16]
[ORG 0x7C00]

section bootloader

jmp main

main:
    ; Set up segment registers
    mov ax, 0x07C0
    mov ds, ax
    mov es, ax

    ; Load the kernel into memory
    mov bx, 0x8000      ; Destination memory address
    mov ah, 0x02        ; Read sector function
    mov al, 1           ; Number of sectors to read
    mov dl, 0x80        ; Boot drive number
    mov ch, 0           ; Cylinder number
    mov dh, 0           ; Head number
    mov cl, 2           ; Sector number
    int 0x13            ; Disk interrupt

    ; Jump to the loaded kernel
    jmp 0x8000:0000

times 510 - ($ - $$) db 0
dw 0xAA55 ; Boot signature

Kernel代码

[BITS 16]
[ORG 0x8000]

section kernel

start:
    mov ax, 0x07C0  ; Set up segment registers
    mov ds, ax
    mov es, ax

    ; Clear the screen
    mov ah, 0x00    ; Video BIOS - Set video mode
    mov al, 0x03    ; Mode 3 (Text mode: 80x25, 16 colors)
    int 0x10        ; Video interrupt

    ; Print the menu options
    mov si, menu
    call printString

    ; Wait for user input
    call readChar

    ; Process user input
    cmp al, '1'
    je option1
    cmp al, '2'
    je option2
    jmp invalidOption

option1:
    mov si, msgOption1
    call printString
    jmp end

option2:
    mov si, msgOption2
    call printString
    jmp end

invalidOption:
    mov si, msgInvalid
    call printString

end:
    ; Halt the system
    cli
    hlt

printString:
    lodsb           ; Load the next character from string
    test al, al     ; Check if end of string
    jz done         ; If yes, return
    mov ah, 0x0E    ; Video BIOS - Teletype output
    mov bh, 0x00    ; Video page
    int 0x10        ; Video interrupt
    jmp printString ; Print next character

done:
    ret

readChar:
    mov ah, 0x00    ; BIOS - Wait for key press
    int 0x16        ; Keyboard interrupt
    ret

menu db 'Welcome to aiOS!', 0x0D, 0x0A, 'Select an option:', 0x0D, 0x0A, '1. Option 1', 0x0D, 0x0A, '2. Option 2', 0x0D, 0x0A, 0x00
msgOption1 db 'You selected Option 1.', 0x0D, 0x0A, 0x00
msgOption2 db 'You selected Option 2.', 0x0D, 0x0A, 0x00
msgInvalid db 'Invalid option.', 0x0D, 0x0A, 0x00

times 510 - ($ - $$) db 0
dw 0xAA55 ; Boot signature

关键排查点与修复方案

1. 致命错误:Bootloader加载地址与跳转地址不匹配

Bootloader中:

  • ES寄存器被设为0x07C0,BX是0x8000,因此Kernel被加载到物理地址 0x07C0 * 16 + 0x8000 = 0xF000
  • 跳转指令jmp 0x8000:0000指向的物理地址是0x8000 * 16 + 0 = 0x80000

两个地址完全不重叠,导致跳转到空内存区域,自然无输出。

修复方案二选一:

方案A:调整Bootloader的ES寄存器,让加载地址匹配跳转地址

修改Bootloader的段寄存器设置:

main:
    ; Set up segment registers
    mov ax, 0x0000
    mov ds, ax
    mov es, ax ; ES设为0,此时ES:BX=0x0000:0x8000,对应物理地址0x8000

    ; Load the kernel into memory
    mov bx, 0x8000      ; Destination memory address
    ; ... 其他磁盘读取代码不变

    ; Jump to the loaded kernel
    jmp 0x0000:0x8000   ; 或直接jmp 0x8000,CS=0,IP=0x8000对应物理地址0x8000

同时修改Kernel的段寄存器设置:

start:
    mov ax, 0x0000  ; 与Bootloader的ES一致
    mov ds, ax
    mov es, ax
方案B:调整跳转地址到实际加载的物理地址

Bootloader中Kernel加载到物理地址0xF000,对应段:偏移为0x0F00:0000,修改跳转指令:

; Jump to the loaded kernel
jmp 0x0F00:0000

修改Kernel的ORG和段寄存器:

[BITS 16]
[ORG 0x0000] ; 因为段地址是0x0F00,偏移从0开始

section kernel

start:
    mov ax, 0x0F00  ; 对应加载的段地址
    mov ds, ax
    mov es, ax

2. 移除Kernel中的冗余引导签名

Kernel不是引导扇区,不需要times 510 - ($ - $$) db 0和dw 0xAA55,这会强制Kernel大小对齐到512字节,可能截断代码或填充无效数据,直接删除这两行。

3. 添加磁盘读取错误处理

Bootloader调用int 0x13后未检查返回值,磁盘读取可能失败。添加错误判断逻辑:

int 0x13
jc disk_error ; CF位置位表示读取失败

; ... 跳转Kernel代码

disk_error:
    mov ah, 0x0E
    mov al, 'E'
    mov bh, 0x00
    int 0x10 ; 输出'E'提示读取失败
    cli
    hlt

4. 验证BIOS中断可用性

在Bootloader中添加简单输出测试,确认BIOS中断正常工作:

main:
    mov ax, 0x0000
    mov ds, ax
    mov es, ax

    ; 测试输出
    mov ah, 0x0E
    mov al, 'B'
    mov bh, 0x00
    int 0x10 ; 屏幕显示'B'

    ; ... 后续加载Kernel代码

如果能显示'B',说明BIOS中断正常,问题集中在Kernel段地址匹配上。

5. 物理硬件兼容性优化

部分现代硬件对CHS模式磁盘读取支持不佳,建议改用LBA模式读取:

; 替换原CHS读取代码为LBA模式
mov ah, 0x42 ; LBA读取功能号
mov dl, 0x80 ; 启动驱动器
mov si, dap  ; DAP指针
int 0x13
jc disk_error

; DAP(磁盘地址包)定义
dap:
    db 0x10        ; DAP大小(固定16字节)
    db 0           ; 保留位
    dw 1           ; 读取扇区数
    dw 0x8000      ; 目标内存偏移
    dw 0x0000      ; 目标内存段地址
    dq 1           ; LBA扇区号(引导扇区是0,Kernel是1)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:49:50