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
问题分析与解决方案
硬编码驱动器号导致读取失败
Bootloader启动时,BIOS会将引导驱动器的编号存入dl寄存器,代码中硬编码mov dl,0会覆盖这个正确值,导致int 13h读取错误的驱动器,返回空数据但未触发错误标志。
解决方案:删除boot.asm中的mov dl,0行,直接使用BIOS提供的dl值。Kernel执行后可能跑飞
hlt指令会暂停CPU,但如果有外部中断触发,CPU会继续执行后续代码(此处为数据段内容),导致无法停留在预期状态。
解决方案:在kernel.asm的hlt后添加jmp $,确保CPU进入无限循环。
修改后重新编译运行,Kernel的-字符应该能正常显示。
内容的提问来源于stack exchange,提问作者someuser
相关产品推荐
相关产品推荐

