DOSBox汇编程序:除法法显示大数出错及万级以上数显示方法
汇编程序显示数字错误的修正及大数显示方法
一、1332显示错误的原因及修正
你的代码存在两个关键错误:
- 寄存器误用导致余数丢失:显示第一个数字时修改了
DL(DX的低8位),破坏了原本存储余数332的DX。你已将余数存入BX,但后续错误地使用DX而非BX加载被除数。 - 8位除法的余数寄存器混淆:当除数为8位(如
HUNDRED DB 100)时,DIV指令的余数存在AH而非DX,DX仅在16位除法(除数为16位)时作为余数寄存器。
修正后的完整代码
.MODEL SMALL .STACK 100 .DATA THOUSAND DW 1000 HUNDRED DB 100 TEN DB 10 NL DB 0DH,0AH,'$' .CODE MAIN PROC MOV AX,@DATA MOV DS,AX MOV DX, 0 MOV AX, 1332 DIV THOUSAND ; 16位除法:DX:AX / 1000,商AX=1,余数DX=332 MOV BX, DX ; 保存余数332到BX,避免DX被后续操作破坏 MOV CL, AL ; 千位数字1存入CL ; 显示千位 MOV AH, 02H MOV DL, CL ADD DL, 30H INT 21H MOV AX, BX ; 从BX加载余数332到AX DIV HUNDRED ; 8位除法:AX / 100,商AL=3,余数AH=32 MOV BH, AH ; 保存余数32到BH MOV CL, AL ; 百位数字3存入CL ; 显示百位 MOV AH, 02H MOV DL, CL ADD DL, 30H INT 21H ; 处理十位和个位 MOV AH, 0H MOV AL, BH ; 从BH加载余数32到AL DIV TEN ; 8位除法:AL /10,商AL=3,余数AH=2 MOV CL, AL ; 十位数字3存入CL MOV CH, AH ; 个位数字2存入CH ; 显示十位 MOV AH, 02H MOV DL, CL ADD DL, 30H INT 21H ; 显示个位 MOV AH, 02H MOV DL, CH ADD DL, 30H INT 21H ; 换行 MOV AH, 09H LEA DX, NL INT 21H MOV AX,4C00H INT 21H MAIN ENDP END MAIN
二、显示10000以上数字的方法
10000~65535的数字可直接用AX存储;超过65535的数字需用DX:AX组合存储32位数值。通用思路是反复除以10收集余数(对应每一位数字),最后逆序输出,可通过栈或缓冲区实现。
示例:通用16位数字显示子程序
以下子程序可打印AX中的16位无符号十进制数:
.MODEL SMALL .STACK 100 .DATA NL DB 0DH,0AH,'$' BUFFER DB 6 DUP(?) ; 最多存储5位数字+结束符 .CODE MAIN PROC MOV AX,@DATA MOV DS,AX MOV AX, 12345 ; 测试10000以上的数字 CALL PRINT_DECIMAL ; 换行 MOV AH,09H LEA DX,NL INT 21H MOV AX,4C00H INT 21H MAIN ENDP ; 子程序:打印AX中的无符号十进制数 ; 输入:AX = 待打印的数字 ; 输出:无(直接调用INT21H输出) PRINT_DECIMAL PROC MOV SI, OFFSET BUFFER + 5 ; 指向缓冲区末尾 MOV BYTE PTR [SI], '$' ; 设置字符串结束符 MOV BX, 10 ; 除数10 NEXT_DIGIT: XOR DX,DX ; DX清零,准备16位除法 DIV BX ; DX:AX /10,商AX,余数DX ADD DL, 30H ; 余数转ASCII字符 DEC SI ; 缓冲区指针前移 MOV [SI], DL ; 存储字符 CMP AX, 0 ; 商为0则结束循环 JNE NEXT_DIGIT ; 输出字符串 MOV AH,09H LEA DX,SI INT 21H RET PRINT_DECIMAL ENDP END MAIN
原理说明
- 用缓冲区从后往前存储每一位的ASCII字符;
- 每次除以10得到当前最低位数字,转成ASCII后存入缓冲区;
- 商为0时停止,从缓冲区第一个有效字符开始输出;
- 若处理32位数字(
DX:AX),去掉DIV BX前的XOR DX,DX即可直接用DX:AX作为被除数。
内容的提问来源于stack exchange,提问作者Lumi Nanodesu
相关产品推荐
相关产品推荐

