在QEMU中运行简易Bootloader与虚拟内核仅输出$的问题求助
问题:Bootloader加载内核后仅输出$符号,无法执行内核代码
编译启动过程无报错,仅QEMU提示probing guessed raw警告,但最终仅显示$符号,内核的!未输出。
现有代码
Bootloader代码(boot.asm)
[org 0x7c00] [bits 16] bt: mov ax, 0x0201 mov bx, 0x1000 mov cx, 0x0002 mov dx, 0x0000 mov es, bx int 0x13 jc dsk_err mov ax, 0x0e24 ;print '$' mov bh, 0 int 0x10 jmp 0x1000:0x00 dsk_err: mov ax, 0x0e21 ;print '!' mov bh, 0 int 0x10 hlt times 510-($-$$) db 0 dw 0xaa55
内核代码(kernel.asm)
[org 0] [bits 16] section .text global _start _start: mov ax, 0x0e21 ;print '!' to make sure it works mov bh, 0 int 0x10 hlt times 510-($-$$) db 0 dw 0xaa55
分隔文件zero.bin
由以下代码编译生成:
times 0x1000-512 db 0
镜像制作命令:
cat boot.bin zero.bin kernel.bin > disk.img
问题分析
缓冲区地址错误:
int 0x13(读磁盘扇区)将数据写入ES:BX指向的内存地址。现有代码中mov bx, 0x1000后又mov es, bx,导致ES=0x1000、BX=0x1000,实际写入地址为0x1000*16 + 0x1000 = 0x11000,但后续跳转的是0x1000:0x00(即物理地址0x10000),两者不匹配,跳转到了无有效代码的区域。扇区编号错误:
zero.bin大小为0x1000-512=3584字节,对应3584/512=7个磁盘扇区。Bootloader占第1扇区,zero.bin占第2-8扇区,内核实际在第9扇区。现有代码中cx=0x0002读取的是第2扇区(zero.bin的起始部分),而非内核所在扇区。
修正方案
修改后的Bootloader代码
[org 0x7c00] [bits 16] bt: mov ax, 0x0201 ; AH=02h(读扇区),AL=1(读1个扇区) mov bx, 0x0000 ; BX=0,作为缓冲区偏移 mov cx, 0x0009 ; CH=0(柱面号低8位),CL=09h(扇区9,柱面号高2位为0) mov dx, 0x0000 ; DL=0(软盘驱动器),DH=0(磁头0) mov es, 0x1000 ; ES=0x1000,缓冲区段地址 int 0x13 jc dsk_err mov ax, 0x0e24 ; 输出$ mov bh, 0 int 0x10 jmp 0x1000:0x00 ; 跳转到内核入口(0x1000:0x00 = 0x10000) dsk_err: mov ax, 0x0e21 ; 输出!表示读盘错误 mov bh, 0 int 0x10 hlt times 510-($-$$) db 0 dw 0xaa55
验证步骤
- 重新编译各文件:
nasm -f bin boot.asm -o boot.bin nasm -f bin kernel.asm -o kernel.bin nasm -f bin zero.asm -o zero.bin - 重新生成镜像:
cat boot.bin zero.bin kernel.bin > disk.img - 启动QEMU:
qemu-system-i386 -fda disk.img
此时应该能看到先输出$,随后输出!,表示内核成功执行。
内容的提问来源于stack exchange,提问作者kwphil
相关产品推荐
相关产品推荐

