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

汇编二级引导加载程序错误消息无法显示问题求助

二级引导加载程序错误消息无法显示的问题

我是汇编语言初学者,正在编写基础二级引导加载程序。目前除错误处理外其余功能正常——即便出现“Partition Table error!”或“Kernel partition cannot be found”这类错误,屏幕上始终只显示“Starting the operating system...”。我怀疑是启动消息覆盖了错误提示,但排查后找不到原因,试过修改光标位置、移除启动消息都没用,测试环境是QEMU虚拟机。

代码片段

ORG 0x8000
BITS 16

section .data
    buffer db 16 dup(0)
    pit_info db 16 dup(0)
    active_partition_info dw 0
 
section .text
    global start

start:
    mov ah, 0x00
    mov al, 0x03
    int 0x10
    mov si, starting_message
    call print
    mov ax, 0x8000
    mov ds, ax
    mov es, ax
    mov ah, 0x02
    mov al, 0x01
    mov ch, 0x00
    mov dh, 0x00
    mov dl, 0x80
    mov bx, buffer
    int 0x13
    jc error_missing_pit
    xor cx, cx
    mov si, buffer

loop:
    mov ax, [si + 0x1C]
    test ax, ax
    jnz found_bootable
    add si, 16
    inc cx
    cmp cx, 0
    jz no_bootable
    jmp loop

found_bootable:
    mov di, pit_info
    mov cx, 16
    rep movsb
    mov ax, [si + 0x08]
    mov [active_partition_info], ax
    mov ax, [si + 0x0C]
    mov [active_partition_info + 2], ax
    mov ah, 0x02
    mov bh, 0x00
    mov db 0x03
    mov dl, 0x00
    int 0x10
    mov si, partition_found_message
    call print 
    jmp kernel_load

error_missing_pit:
    mov si, missing_pit
    call print
    cli
    hlt

no_bootable:
    mov si, no_partition
    call print
    cli
    hlt

starting_message:
    db "Starting the operating system...", 0x0A, 0

missing_pit: 
     db "Partition Table error!", 0x0A, 0

no_partition:
     db "Kernel partition cannot be found - does it have the active flag?", 0x0A, 0

print:
    mov bx, 0
    call print_loop
    ret

print_loop:
    mov al, [si] 
    cmp al, 0 
    je print_done 
    mov ah, 0x0E 
    int 0x10 
    inc si 
    jmp print_loop

print_done:
    ret

kernel_load:
    ;.........

partition_found_message:
    db "Kernel partition found!", 0x0A, 0

核心问题与修复步骤

1. 段寄存器初始化时机错误

调用print输出启动消息前,未将ds寄存器设置为程序段地址0x8000。BIOS将二级引导加载到0x8000物理地址,ORG 0x8000意味着所有符号偏移基于该地址,必须先设置ds=0x8000才能正确访问字符串数据。

修复:调整段寄存器设置位置到call print之前:

start:
    mov ah, 0x00
    mov al, 0x03
    int 0x10
    ; 先初始化段寄存器
    mov ax, 0x8000
    mov ds, ax
    mov es, ax
    mov si, starting_message
    call print
    ; 后续代码...

2. 分区表遍历逻辑完全错误

  • 初始指针指向错误:MBR分区表从偏移0x1BE开始,应将si初始化为buffer + 0x1BE而非buffer。
  • 活动标志检查位置错误:每个分区项的活动标志是第一个字节(偏移0x00),值为0x80表示活动,而非si+0x1C位置的双字。
  • 循环终止条件错误:原代码用cmp cx,0判断循环结束,而cx初始为0后每次循环递增,永远不会等于0,应检查cx是否等于4(最多4个主分区)。

修复loop部分代码:

xor cx, cx
    mov si, buffer + 0x1BE  ; 指向分区表起始位置

loop:
    mov al, [si]            ; 读取分区活动标志字节
    cmp al, 0x80            ; 检查是否为活动分区
    je found_bootable
    add si, 16              ; 跳到下一个分区项
    inc cx
    cmp cx, 4               ; 检查是否遍历完4个分区
    jl loop                 ; 未遍历完继续循环

no_bootable:
    mov si, no_partition
    call print
    cli
    hlt

3. 非法指令导致崩溃

found_bootable分支中的mov db 0x03是非法指令,属于笔误,应改为设置光标行号的mov dh, 0x03。

修复:

found_bootable:
    mov di, pit_info
    mov cx, 16
    rep movsb
    mov ax, [si + 0x08]
    mov [active_partition_info], ax
    mov ax, [si + 0x0C]
    mov [active_partition_info + 2], ax
    mov ah, 0x02            ; BIOS设置光标位置调用
    mov bh, 0x00            ; 视频页号
    mov dh, 0x03            ; 光标行号(改为合法寄存器操作)
    mov dl, 0x00            ; 光标列号
    int 0x10
    mov si, partition_found_message
    call print 
    jmp kernel_load

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 07:07:07