汇编技术问题:引导程序打印十六进制数时出现意外叠加
嘿,这种打印十六进制数时的叠加问题我太熟了!十有八九是你的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
相关产品推荐
相关产品推荐

