自制操作系统Bootloader打印异常:Qemu仅输出'U'求排查
问题原因及修复方案
核心问题1:段寄存器DS未初始化
BIOS加载引导扇区时,DS寄存器的值并非固定为0,而你的代码通过ORG 0x7c00假设内存访问基于DS=0(物理地址=DS×16+偏移),导致[si]读取到错误的内存区域,恰好命中引导签名的0x55(对应字符'U')。
核心问题2:打印函数存在冗余与不规范
- 多余的
ret指令(psloop块外的ret永远不会执行,可删除) - 未初始化BIOS中断所需的辅助寄存器(BH=页码、BL=前景色)
- 循环逻辑可优化,先检查字符是否为结束符再调用中断,避免无效执行
修复后的主代码
ORG 0x7c00 BITS 16 %include "lib/print.asm" boot: ; 初始化段寄存器DS为0,确保内存访问地址正确 xor ax, ax mov ds, ax mov es, ax mov si, boot_msg call Print jmp $ boot_msg: db "The os is correctly loaded!", 0 times 510 - ($ - $$) db 0 dw 0xAA55
修复后的打印函数(lib/print.asm)
Print: ; BIOS 0x10中断:Teletype输出模式,AH=0x0E mov ah, 0x0e ; 设置页码BH=0,前景色BL=0x07(白字黑底,文本模式默认) mov bh, 0x00 mov bl, 0x07 print_loop: mov al, [si] ; 加载当前字符到AL cmp al, 0 ; 检查是否为字符串结束符 je print_done ; 是则退出循环 int 0x10 ; 调用BIOS中断打印字符 inc si ; 指针移动到下一个字符 jmp print_loop print_done: ret
验证方式
重新编译代码后用Qemu运行,即可正常输出完整字符串。
内容的提问来源于stack exchange,提问作者Federico Occhiochiuso
相关产品推荐
相关产品推荐

