You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

引导加载程序中Int 10h ah=0eh输出异常,自定义OS打印函数故障排查

解决print_string函数输出乱码的问题

看起来你的字符串打印函数逻辑本身没问题,但输出的是乱码Wn=Wn=而不是预期的"hello",大概率是段寄存器不匹配或者DF标志异常导致的,我来帮你排查下:

首先,先看几个关键问题点:

1. 段寄存器DS和Msg所在段不匹配

实模式下内存地址是「段寄存器值左移4位 + 偏移量」,你只给SI设置了Msg的偏移量,但如果DS寄存器的段基址和Msg实际所在的段不一样,那DS:SI指向的就不是你定义的"hello",而是内存里的随机垃圾数据,自然输出乱码。

比如如果你的代码是bootloader(加载到0x7C00),启动时CS寄存器的值是0x07C0,但DS默认可能是0x0000,这时候你直接用SI指向Msg的偏移量,实际访问的是0x0000:offset,而不是0x07C0:offset(也就是0x7C00+offset),完全不是你定义的字符串。

解决方法:在调用print_string前,把DS设置成和Msg所在的段一致。如果Msg在代码段里,直接把CS的值传给DS就行:

mov ax, cs
mov ds, ax  ; 让DS和CS同段,确保偏移量正确

2. DF标志导致SI反向读取

lodsb指令的行为受DF方向标志影响:如果DF是0(默认应该是0),SI会自动+1,依次读取下一个字符;如果DF被不小心设成1,SI会-1,导致重复读取前面的字节,也会出现乱码。

保险起见,在调用函数前加一句cld来强制设置DF为0:

cld  ; 确保SI按递增方向读取字符串

3. 确认Msg的终止符是否正确

你提到Msg内容是"hello",要确保定义时加了终止符0,不然lodsb会一直读内存直到碰巧遇到0,也可能输出乱码:

Msg db 'hello', 0  ; 必须加0作为字符串结束标记

修正后的完整示例代码

把这些修正点加进去,代码应该就正常了:

; 初始化段寄存器和方向标志
mov ax, cs
mov ds, ax
cld

; 调用打印函数
mov si, Msg
call print_string

; 字符串打印函数
print_string: 
    pusha 
    mov ah, 0Eh      ; int 10h的0Eh功能:Teletype输出
.repeat: 
    lodsb            ; 读取DS:SI指向的字节到AL,SI自动增减
    cmp al, 0        ; 判断是否到字符串结束
    je .done 
    int 10h          ; 调用BIOS中断打印字符
    jmp .repeat 
.done: 
    popa 
    ret

; 定义字符串
Msg db 'hello', 0

这样调整后,应该就能正确输出"hello"了。

内容的提问来源于stack exchange,提问作者Gamer0010101

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:40:07