8086汇编统计零位后打印报错INT 21h, AH=09h的原因及解决方法
解决INT 21h AH=09h报错:零位数统计代码的修复
兄弟,你的统计逻辑没问题,报错完全是因为用错了DOS功能调用INT 21h AH=09h的参数规则!
报错原因拆解
先给你明确一下INT 21h AH=09h的要求:这个功能是用来打印以$结尾的字符串的,它要求DX寄存器里存放的是该字符串在内存中的偏移地址,而不是直接把ASCII码值塞进去。
你原代码里做完统计后,把零位数转成ASCII(add cx,48)就直接把cx赋值给dx去调用09h,DOS会误以为dx是内存地址,跑去那个地址开始找$结束符,结果搜了2000字节都没找到,自然就抛出那个错误了。
修复方案
我们需要先把统计得到的零位数转换成一个带$结束符的字符串,再让DX指向它的地址。具体步骤:
- 在
.data段定义一个字节变量(或者小缓冲区)用来存数字和结束符; - 把CH里的零位数(你用CH存的零计数器,CL是循环次数)转成ASCII,放到这个变量里;
- 调用09h时,让DX指向这个变量的偏移地址。
修改后的完整代码
.model small .stack 100h .data num db 10111111b itr db 8 ; 改成8更准确,因为num是8位字节,要循环8次统计所有位 result db ? ; 用来存转换后的ASCII数字 dollar db '$' ; 字符串结束符 .code mov ax, @data mov ds, ax mov cl,0 ; 循环次数计数器 mov ch,0 ; 零位数计数器 next: rol num, 1 jnc isZero inc cl cmp cl, itr je stop jmp next isZero: inc ch inc cl ; 原代码这里漏了!不递增循环计数器会导致死循环 jmp next stop: ; 把CH里的零位数转成ASCII,存到result里 mov al, ch add al, 48 ; 数字0-9转ASCII,加48即可 mov result, al ; 调用INT 21h AH=09h打印字符串 mov ah, 9 lea dx, result ; DX指向result的偏移地址 int 21h .exit end
额外提醒
原代码里还有个隐藏坑:isZero分支里没有递增cl(循环计数器),这会导致循环永远达不到itr的次数,直接陷入死循环!我已经在修改后的代码里补上了,你可以留意一下。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

