汇编二级引导加载程序错误消息无法显示问题求助
二级引导加载程序错误消息无法显示的问题
我是汇编语言初学者,正在编写基础二级引导加载程序。目前除错误处理外其余功能正常——即便出现“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
相关产品推荐
相关产品推荐

