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

汇编技术问题:引导程序打印十六进制数时出现意外叠加

嘿,这种打印十六进制数时的叠加问题我太熟了!十有八九是你的print_hex函数没做好状态清理,导致第二次调用时带上了第一次的残留数据。我帮你拆解几个最常见的坑和修复思路:

常见问题原因

  • 缓冲区没重置:很多汇编打印十六进制的实现会用一个固定的字符串缓冲区(比如hex_str db '0x00000000', 0),第一次打印后缓冲区里存了第一个数的字符,第二次如果没先把缓冲区重置成初始的全0状态,就会在旧内容上部分覆盖,看起来就是两个数叠加在了一起。
  • 寄存器未保存/恢复:如果print_hex函数修改了BX、SI这类需要保留的寄存器,又没在函数开头压栈、结尾恢复,第一次调用后这些寄存器的值被改变,第二次调用时参数或内部指针就会乱掉。
  • 字符处理逻辑不全:比如只处理了十六进制数的前几位,剩下的位数还留着上次的字符,自然就会叠加。

修复建议

我给你一个经过验证的print_hex实现模板,你可以对照着改自己的代码:

; 功能:打印DX寄存器中的32位十六进制数(实模式下可扩展为DX:AX)
; 依赖:需要有print_string函数来打印字符串
print_hex:
    pusha               ; 先把所有通用寄存器压栈,避免干扰调用者
    mov cx, 8           ; 要处理8个十六进制字符(对应32位,16位的话设为4)
    mov si, hex_str + 2 ; 指向缓冲区中第一个要修改的位置(跳过'0x')

; 第一步:先把缓冲区重置为全'0'
reset_buf:
    mov byte [si], '0'
    inc si
    loop reset_buf

; 第二步:把要打印的数逐位转成ASCII字符
    mov si, hex_str + 9 ; 从缓冲区最后一位开始往前写
    mov ax, dx          ; 假设要打印的数存在DX中,32位的话用DX:AX
    mov cx, 8

hex_convert:
    mov bx, ax
    and bx, 0x000F      ; 取出最后4位
    cmp bx, 0x0A
    jl is_digit
    add bx, 0x27        ; 如果是A-F,转成ASCII大写字母(0xA+0x27=0x41='A')

is_digit:
    add bx, 0x30        ; 转成ASCII数字(0-9)
    mov byte [si], bl
    dec si
    shr ax, 4           ; 右移4位,处理下一位
    loop hex_convert

; 第三步:打印处理好的字符串
    mov bx, hex_str
    call print_string

    popa                ; 恢复所有寄存器
    ret

; 全局缓冲区,初始化为0x00000000
hex_str db '0x00000000', 0

额外检查点

  • 每次调用print_hex前,确保你要打印的数已经正确传入对应的寄存器(比如上面的DX),两次调用之间不要让这个寄存器被其他代码修改。
  • 如果你的print_string是直接写显存的,确认它会正确更新光标位置,避免第二次打印从上次的位置开始覆盖。

这样修改后,两次调用print_hex应该就能分别打印出两个独立的十六进制数啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:42:58