求助:汇编编写的引导加载程序无法跳转到加载的磁盘代码
问题分析与修复方案
核心问题1:磁盘读取功能号错误
你的ReadDisk函数里使用了mov ah, 0x01,但BIOS中断int 0x13的读扇区功能号是0x02,0x01是磁盘重置功能。这导致你根本没从磁盘加载4个扇区到0x7E00,虽然打印了"Success!",但目标内存区域是垃圾数据,跳转后自然挂起。
核心问题2:启动磁盘号未初始化
BIOS启动引导扇区时,会把启动磁盘的编号存在dl寄存器里,但你的代码没把这个值保存到BOOT_DISK变量中,后续读磁盘时dl的值可能被破坏,即使功能号正确也会读盘失败。
次要问题:字符串终止判断与栈顺序错误
- 两个
print函数里用cmp word [bx], 0判断字符串结束,但字符串是字节型(db定义),应该用cmp byte [bx], 0,否则会一次性读取两个字节判断,导致打印提前终止或无限循环。 print函数的栈操作顺序错误:push ax后push bx,弹出时应该先pop bx再pop ax,之前的顺序会导致寄存器值混乱。
修复后的代码
start.S 修复版
[BITS 16] [ORG 0x7C00] PROGRAM_SPACE equ 0x7E00 start: mov bp, 0x7c00 mov sp, bp mov [BOOT_DISK], dl ; 保存BIOS传入的启动磁盘号 call ReadDisk mov bx, DiskSuccesString call print jmp PROGRAM_SPACE ; 用宏定义更清晰 hang: jmp hang print: push ax push bx mov ah,0x0e .loop: cmp byte [bx], 0 ; 改为字节判断字符串结束 je .exit mov al,[bx] int 0x10 inc bx jmp .loop .exit: pop bx ; 修正栈弹出顺序 pop ax ret ReadDisk: mov ah, 0x02 ; 修正为读扇区功能号 mov bx, PROGRAM_SPACE mov al,4 mov dl,[BOOT_DISK] mov ch,0x00 mov dh,0x00 mov cl,0x02 int 0x13 jc DiskError ret BOOT_DISK: db 0 DiskError: mov bx, DiskErrorString call print jmp $ DiskErrorString: db 'Error while reading Disk ',0 DiskSuccesString: db 'Success!',0 ; 修正拼写错误 times 510-($-$$) db 0 db 0x55 db 0xaa
kernel.S 修复版
[BITS 16] [ORG 0x7E00] mov ax, 0x0000 mov ss, ax mov sp, 0xFFFF mov bx, msg call print jmp $ print: push ax push bx mov ah,0x0e .loop: cmp byte [bx], 0 ; 改为字节判断字符串结束 je .exit mov al,[bx] int 0x10 inc bx jmp .loop .exit: pop bx ; 修正栈弹出顺序 pop ax ret msg: db 'Welcome to PotatOS',0 times 2048-($-$$) db 0
内容的提问来源于stack exchange,提问作者Junus Safsouf
相关产品推荐
相关产品推荐

