如何打印整数而非ASCII值?汇编循环求和后输出整数的代码问题
嘿,我来帮你排查下这个问题!你的代码其实已经正确算出了数字总和(1+2+3+4+10=20),但核心问题出在打印环节——你用的DOS中断功能不对,导致输出的是ASCII字符而非数字本身,另外我也会教你如何正确打印整数。
你的代码里的核心问题
- 打印功能误用:
mov ah, 02h+int 21h是DOS的「输出ASCII字符」功能,它会把DL寄存器里的数值当作ASCII码输出。你的总和是20,对应的ASCII是空格字符,所以屏幕上看不到预期的数字。 - 补充:求和逻辑是没问题的——
xor ax,ax清零累加器、mov bx,tabl指向数组首地址、循环累加字节元素的步骤都正确,最终AX里确实存着正确的总和20。
如何打印整数(十进制)
要打印整数,你需要先把二进制数值转换成十进制数字对应的ASCII字符,再逐个输出。比如20要拆成'2'和'0',它们的ASCII码分别是50和48。具体步骤是:
- 用除法拆分数字:把数值不断除以10,得到的余数就是当前的个位数字,将余数加48转换成ASCII(因为'0'的ASCII是48)。
- 用栈反转顺序:因为除法得到的数字是从个位到高位的顺序,压入栈再弹出就能变成我们阅读的高位到个位顺序。
- 逐个弹出栈内的ASCII字符,用
02h功能打印。
修正后的完整代码
format MZ stack sth:256 entry codeseg: main segment sdat use16 ;ds segment x tabl db 1,2,3,4,10 segment sth use16 db 256 dup (?) segment codeseg use16 main: mov ax, sdat mov ds, ax ; 打开栈初始化代码,确保程序栈正常工作 mov ax, sth mov ss, ax mov sp, 256 xor ax,ax ; AX清零,用来存储总和 mov bx,tabl ; BX指向数组首地址 mov cx,5 ; 循环次数设置为5 add_loop: ; 给循环起个清晰的名字,避免和add指令重名 add al,[bx] ; 数组是字节类型,直接累加至AL更高效(AH初始为0) inc bx loop add_loop ; CX减1,不为0则跳回循环 ; 现在AX中是总和20,开始转换并打印 mov bx, 10 ; 设置除数为10,用于拆分数字 mov cx, 0 ; CX用来记录数字的位数 convert: xor dx, dx ; DIV指令使用DX:AX作为被除数,先清零DX div bx ; AX = AX / 10(商),DX = AX % 10(余数,即当前位数字) add dl, 48 ; 把余数转换成对应的ASCII字符(0-9对应48-57) push dx ; 将ASCII字符压入栈,用于后续反转顺序 inc cx ; 位数计数+1 cmp ax, 0 ; 检查商是否为0,不为0则继续拆分 jne convert ; 从栈中弹出字符并逐个打印 print: pop dx ; 弹出一位的ASCII码到DL mov ah, 02h ; DOS功能:输出DL中的ASCII字符 int 21h loop print ; CX减1,不为0则继续打印 ; 程序正常退出 mov ax, 4c00h int 21h ret
关键部分说明
- 求和优化:因为数组元素是字节,直接用
add al,[bx]更高效,不需要操作整个AX寄存器。 - 数字转ASCII:通过
div 10拆分出每一位数字,加48是ASCII码的偏移量,确保数字0-9对应'0'-'9'。 - 栈的作用:拆分得到的数字是个位→十位的顺序,压栈后弹出就变成十位→个位,符合我们的阅读习惯。
- 栈初始化:把你注释掉的栈初始化代码打开,避免程序运行时出现栈溢出等潜在问题。
运行这段代码后,屏幕上就会正确打印出20了!
内容的提问来源于stack exchange,提问作者Paweł




