汇编语言计算器异常求助:加减乘输出0、除法溢出报错
汇编计算器问题排查与修复
核心问题根源
- 数字转换逻辑完全错误:
readNumber过程中的数值转换逻辑颠倒,导致输入的所有数字都被转换为0,直接引发加减乘结果为0。 - 除法未做除数校验:未检查除数是否为0,当转换后的除数为0时触发CPU除零异常,出现"divide error - overflow"错误。
具体错误拆解
1. readNumber转换逻辑错误
原代码中错误地使用cx作为累计值,且乘法顺序完全颠倒:
mul cx ; 初始cx为0,第一次相乘结果始终为0,后续累加也无法得到正确数值
正确逻辑应为:用ax保存累计值,每次将累计值乘10,再加上当前输入的数字(ASCII转数值后)。
2. 除法无除数检查
执行div bx前未判断bx(除数)是否为0,当除数为0时,CPU会触发除零异常,直接终止程序并抛出错误。
修正后的完整代码
.model small .stack 100h .data greeting db 'WELCOME TO YOUR CALCULATOR', 0Dh, 0Ah, '$' menu db '1 - ADDITION', 0Dh, 0Ah, '2 - SUBTRACTION', 0Dh, 0Ah, '3 - MULTIPLICATION', 0Dh, 0Ah, '4 - DIVISION', 0Dh, 0Ah, '$' choicePrompt db 'Enter your choice: $' prompt1 db 'Enter 1st Number: $' prompt2 db 'Enter 2nd Number: $' resultMsg db 'The result is: $' errorMsg db 'Error: Division by zero!$' buffer db 6, 0, 5 dup(0) ; 最多存储5位数字的输入缓冲区 userChoice db 0 num1 dw 0 num2 dw 0 result dw 0 .code main proc mov ax, @data mov ds, ax ; 打印欢迎语和菜单 lea dx, greeting mov ah, 09h int 21h lea dx, menu mov ah, 09h int 21h ; 打印选择提示 lea dx, choicePrompt mov ah, 09h int 21h ; 读取用户选择 mov ah, 01h int 21h sub al, '0' mov userChoice, al call getch ; 打印换行 call printNewline ; 打印第一个数字提示并读取 lea dx, prompt1 mov ah, 09h int 21h call readNumber mov num1, ax call printNewline ; 打印第二个数字提示并读取 lea dx, prompt2 mov ah, 09h int 21h call readNumber mov num2, ax ; 执行选择的运算 mov ax, num1 mov bx, num2 cmp userChoice, 1 je additionOp cmp userChoice, 2 je subtractionOp cmp userChoice, 3 je multiplicationOp cmp userChoice, 4 je divisionOp jmp endProgram additionOp: add ax, bx mov result, ax jmp displayResult subtractionOp: sub ax, bx mov result, ax jmp displayResult multiplicationOp: mul bx mov result, ax ; 注:若乘积超过16位,需处理dx中的高位部分 jmp displayResult divisionOp: cmp bx, 0 ; 检查除数是否为0 je divisionError xor dx, dx div bx mov result, ax jmp displayResult divisionError: call printNewline lea dx, errorMsg mov ah, 09h int 21h jmp endProgram displayResult: ; 打印结果提示 lea dx, resultMsg mov ah, 09h int 21h ; 打印结果数值 mov ax, result call printNumber ; 打印换行 call printNewline ret endProgram: mov ah, 4Ch int 21h main endp getch proc mov ah, 07h int 21h ret getch endp readNumber proc lea dx, buffer mov ah, 0Ah int 21h lea si, buffer + 2 mov ax, 0 ; ax用于累计转换后的数值,初始为0 convertLoop: lodsb ; 读取缓冲区中的下一个字符到al cmp al, 0Dh ; 检查是否为回车符 je endConvert sub al, '0' ; 将ASCII字符转换为数字0-9 mov cx, ax ; 临时保存当前数字 mov bx, 10 mul bx ; ax = ax * 10(将累计值左移一位,相当于乘10) add ax, cx ; 加上当前数字,更新累计值 jmp convertLoop endConvert: ret readNumber endp printNewline proc mov ah, 02h mov dl, 0Dh int 21h mov dl, 0Ah int 21h ret printNewline endp printNumber proc mov bx, 10 xor cx, cx convertLoop2: xor dx, dx div bx add dl, '0' push dx inc cx cmp ax, 0 jne convertLoop2 printLoop: pop dx mov ah, 02h int 21h loop printLoop ret printNumber endp end main
修正点说明
- 修复数字转换逻辑:
- 改用
ax作为累计值存储变量,执行ax = ax*10 + 当前数字的正确转换逻辑,确保输入的数字能被正确转换为整数存入num1和num2。
- 改用
- 新增除数校验:
- 在除法运算前检查除数是否为0,若为0则输出错误提示并跳过除法操作,避免触发CPU除零异常。
- 添加错误提示:
- 在数据段新增
errorMsg字符串,用于显示除零错误信息,提升程序的健壮性。
- 在数据段新增
内容的提问来源于stack exchange,提问作者Gigi20
相关产品推荐
相关产品推荐

