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

NASM编写Bootloader调用BIOS int 13h加载Kernel失败求助

Bootloader加载Kernel失败排查

问题描述

编写简易Bootloader加载Kernel时,Bootloader的打印信息正常显示,但Kernel中的-字符从未输出。运行时仅能看到Bootloader的问候与加载提示(VGA设置信息因BIOS中断清屏未显示)。

相关代码

boot.asm

bits 16
org 0x7c00

; 设置VGA模式
mov bx, MsgVga
call bios_print

mov ah, 0x00
mov al, 0x03
int 0x10

mov bx, MsgGreet
call bios_print

mov bx, MsgKernel
call bios_print

; 加载kernel
mov ah, 02h ; 读扇区功能号
mov al, 1   ; 读取扇区数
mov ch, 0   ; 磁道号
mov cl, 2   ; 起始扇区号
mov dh, 0   ; 磁头号
; 移除硬编码的mov dl,0,使用BIOS提供的引导驱动器号
mov ax, 0x0000
mov es, ax
mov bx, 0x1000 ; 加载目标地址
int 13h

jc .KernelErr

test ah, ah
jnz .KernelErr

push es
push bx
retf

.KernelErr:
mov bx, MsgKernelErr
call bios_print

jmp $

bios_print:
        ; bx指向字符串起始
.l:
        mov al, [bx]
        test al, al
        jz .d
        inc bx
        mov ah, 0x0e
        int 0x10

        jmp .l

.d:
        ret

MsgGreet db 'Hello from cool bootloader!', 0
MsgVga db 'Setting video mode to VGA...', 0
MsgKernel db 'Attempting to load kernel...', 0
MsgKernelErr db 'Error while loading kernel. Entering infinite loop...', 0
times 510 - ($-$$) db 0

dw 0xAA55

kernel.asm

bits 16
org 0x1000

section .text
        global _start

_start:
        ; 输出'-'字符
        mov ah, 0x0E
        mov al, '-'
        int 0x10

        hlt
        jmp $ ; 防止中断唤醒后CPU继续执行

section .data
        text db 'cool text here', 0

times 512 - ($-$$) db 0

编译运行步骤

nasm -f bin boot.asm -o boot.bin
nasm -f bin kernel.asm -o kernel.bin
cat boot.bin kernel.bin > os.img
qemu-system-i386 -fda os.img

os.img十六进制转储

user@fedora:~/os$ hexdump -C os.img
00000000  bb 69 7c e8 39 00 b4 00  b0 03 cd 10 bb 4d 7c e8  |.i|.9........M|.| 
00000010  2d 00 bb 86 7c e8 27 00  b4 02 b0 01 b5 00 b1 02  |-...|.'.........| 
00000020  b6 00 b2 00 b8 00 00 8e  c0 bb 00 10 cd 13 72 07  |..............r.| 
00000030  84 e4 75 03 06 53 cb bb  a3 7c e8 02 00 eb fe 8a  |..u..S...|......| 
00000040  07 84 c0 74 07 43 b4 0e  cd 10 eb f3 c3 48 65 6c  |...t.C.......Hel| 
00000050  6c 6f 20 66 72 6f 6d 20  63 6f 6f 6c 20 62 6f 6f  |lo from cool boo| 
00000060  74 6c 6f 61 64 65 72 21  00 53 65 74 74 69 6e 67  |tloader!.Setting| 
00000070  20 76 69 64 65 6f 20 6d  6f 64 65 20 74 6f 20 56  | video mode to V| 
00000080  47 41 2e 2e 2e 00 41 74  74 65 6d 70 74 69 6e 67  |GA....Attempting| 
00000090  20 74 6f 20 6c 6f 61 64  20 6b 65 72 6e 65 6c 2e  | to load kernel.| 
000000a0  2e 2e 00 45 72 72 6f 72  20 77 68 69 6c 65 20 6c  |...Error while l| 
000000b0  6f 61 64 69 6e 67 20 6b  65 72 6e 65 6c 2e 20 45  |oading kernel. E| 
000000c0  6e 74 65 72 69 6e 67 20  69 6e 66 69 6e 69 74 65  |ntering infinite| 
000000d0  20 6c 6f 6f 70 2e 2e 2e  00 00 00 00 00 00 00 00  | loop...........| 
000000e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
* 
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.| 
00000200  b4 0e b0 2d cd 10 f4 00  63 6f 6f 6c 20 74 65 78  |...-....cool tex| 
00000210  74 20 68 65 72 65 00 00  00 00 00 00 00 00 00 00  |t here..........| 
00000220  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
* 
00000400  00 00 00 00 00 00 00 00                           |........| 
00000408

GDB调试信息

读取前(Bootloader起始地址0x7C00)

(gdb) x/32xb 0x00001000 
0x1000: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00 
0x1008: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00 
0x1010: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00 
0x1018: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00

读取后(跳转至0x00001000前)

(gdb) x/32xb 0x00001000
0x1000: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x1008: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x1010: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x1018: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00

问题分析与解决方案

  1. 硬编码驱动器号导致读取失败
    Bootloader启动时,BIOS会将引导驱动器的编号存入dl寄存器,代码中硬编码mov dl,0会覆盖这个正确值,导致int 13h读取错误的驱动器,返回空数据但未触发错误标志。
    解决方案:删除boot.asm中的mov dl,0行,直接使用BIOS提供的dl值。

  2. Kernel执行后可能跑飞
    hlt指令会暂停CPU,但如果有外部中断触发,CPU会继续执行后续代码(此处为数据段内容),导致无法停留在预期状态。
    解决方案:在kernel.asm的hlt后添加jmp $,确保CPU进入无限循环。

修改后重新编译运行,Kernel的-字符应该能正常显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 01:42:32