Bootloader输出乱码问题求助:次级引导程序显示异常字符
次级Bootloader打印乱码问题排查与修复
核心问题分析
从你提供的代码和现象来看,数据段寄存器(DS)设置时机错误是导致乱码的主要原因:
- 代码开头先调用
print打印启动信息,但此时DS寄存器尚未初始化,默认值指向错误内存区域,读取starting_message时会读到RAM中的垃圾数据,引发乱码。 - 你设置
ds = 0x07C0,但次级引导程序的ORG是0x8000,正确的DS配置应为0x0000(0x0000:0x8000才是次级引导程序加载的物理地址0x8000),错误的段地址会导致所有数据访问偏移出错,进一步触发内存读取异常。
修复步骤
1. 优先初始化数据段寄存器
在调用print函数前,先正确设置DS和ES,确保数据访问地址匹配程序加载位置:
start: mov ah, 0x00 mov al, 0x03 int 0x10 ; 初始化DS/ES为0x0000,匹配ORG 0x8000的加载地址 xor ax, ax mov ds, ax mov es, ax mov si, starting_message call print
2. 修正磁盘读取的段地址
后续调用int 0x13读取分区表时,bx = buffer的地址依赖DS,保持DS为0x0000即可,无需改成0x07C0(该值对应MBR的段地址)。
3. 优化换行符显示(可选)
启动信息结尾的0x0A(换行)无法被BIOS中断int 0x10的0x0E功能自动处理,可修改print函数手动调整光标位置:
print_loop: mov al, [si] cmp al, 0 je print_done cmp al, 0x0A je handle_newline mov ah, 0x0E int 0x10 inc si jmp print_loop handle_newline: ; 获取当前光标位置 mov ah, 0x03 xor bh, bh int 0x10 ; 光标移至下一行开头 mov ah, 0x02 inc dh mov dl, 0 int 0x10 inc si jmp print_loop
4. 主动清零关键数据区(可选)
为避免内存残留数据干扰,可在启动时主动清零buffer、pit_info等变量:
; 初始化DS后执行 mov cx, 16 mov di, buffer xor ax, ax rep stosb mov di, pit_info rep stosb
额外验证点
- 确认次级引导程序加载地址:在QEMU中用
info registers查看CS:IP,或用x/100i 0x8000断点调试代码位置。 - 检查磁盘读取状态:确认
int 0x13读取分区表未失败,避免错误处理分支因DS错误导致异常输出。
内容的提问来源于stack exchange,提问作者Florin Voicu
相关产品推荐
相关产品推荐

