You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

汇编语言计算器异常求助:加减乘输出0、除法溢出报错

汇编计算器问题排查与修复

核心问题根源

  1. 数字转换逻辑完全错误:readNumber过程中的数值转换逻辑颠倒,导致输入的所有数字都被转换为0,直接引发加减乘结果为0。
  2. 除法未做除数校验:未检查除数是否为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

修正点说明

  1. 修复数字转换逻辑:
    • 改用ax作为累计值存储变量,执行ax = ax*10 + 当前数字的正确转换逻辑,确保输入的数字能被正确转换为整数存入num1和num2。
  2. 新增除数校验:
    • 在除法运算前检查除数是否为0,若为0则输出错误提示并跳过除法操作,避免触发CPU除零异常。
  3. 添加错误提示:
    • 在数据段新增errorMsg字符串,用于显示除零错误信息,提升程序的健壮性。

内容的提问来源于stack exchange,提问作者Gigi20

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 10:12:01