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

x86汇编实现计算器时除法功能输出异常问题求助

基础计算器除法功能异常修复

问题现象

选择除法(输入4)后,输入被除数20和除数5,程序输出0/20->20,不符合预期的20/5->4。

问题根源

  1. 除法运算逻辑错误:

    • 未将正确的被除数放入rax寄存器就执行cqo和idiv,导致实际计算的是除数除以被除数,得到商0。
    • 除数为0的判断逻辑错误,当前代码检查的是被除数(r15)而非除数是否为0。
  2. 打印参数顺序完全错误:
    格式串dividestr定义为"%d / %d -> %d\n",对应顺序是「被除数 / 除数 -> 商」,但当前printintdiv传递的参数是「商 / 被除数 -> 除数」,完全匹配错位。

修复方案

  1. 修正除法运算流程:

    • 将被除数(r14)移入rax,用cqo扩展符号位到rdx,准备有符号除法。
    • 先保存除数(原rax值)到临时寄存器,检查除数是否为0,再执行idiv完成除法。
  2. 修正打印参数顺序:
    按照格式串要求,依次传递被除数、除数、商到printf的对应参数寄存器。

  3. 修正除零判断逻辑:
    检查除数而非被除数是否为0,除零场景下正确传递被除数和0作为除数到打印函数。

修正后的完整代码

# CPSC 2500 Winter 2023
# Name:
# Date:

# Compile on Linux using: gcc -g -fno-pie -no-pie ./calc.s -o calc

.bss # block starting symbol, contains allocated but not yet initialized memory
num: # num will hold a 64 bit integer provided by the user
    .skip 8

.data
addstr: # C-style formatting for calling printf()
    .asciz "%d + %d -> %d\n"

minusstr: # C-style formatting for calling printf()
    .asciz "%d - %d -> %d\n"

mutiplystr: # C-style formatting for calling printf()
    .asciz "%d * %d -> %d\n"

dividestr: # C-style formatting for calling printf()
    .asciz "%d / %d -> %d\n"

.text
.global main

getint: # get integer from user
    movq $0, %rax
    movq $0, %rdi
    movq $num, %rsi
    movq $8, %rdx
    syscall # get user input from STDIN

    movq $num, %rdi
    call atoi # convert user input from string to integer
    ret

printint: # print result of addition
    mov $addstr, %rdi
    mov %r14, %rsi
    mov %rax, %rdx
    mov %r15, %rcx
    xor %rax, %rax
    call printf
    ret

printintminus: # print result of subtraction
    mov $minusstr, %rdi
    mov %r14, %rsi
    mov %rax, %rdx
    mov %r15, %rcx
    xor %rax, %rax
    call printf
    ret


printinttimes: # print result of multiplication
    mov $mutiplystr, %rdi
    mov %r14, %rsi
    mov %rax, %rdx
    mov %r15, %rcx
    xor %rax, %rax
    call printf
    ret

printintdiv: # print result of division
    mov $dividestr, %rdi   # Format string
    mov %r14, %rsi         # 被除数
    mov %r12, %rdx         # 除数
    mov %rax, %rcx         # 商
    xor %rax, %rax
    call printf
    ret



end: # terminate program
    mov $60, %rax
    xor %rdi, %rdi
    syscall

main:
    call getint 
    mov %rax, %r13
    cmpq $-1, %r13
    je end
    call getint
    mov %rax, %r15
    call getint
    mov %r15, %r14
    cmpq $1, %r13
    je addtwonums
    cmpq $2, %r13
    je subtwonums
    cmpq $3, %r13
    je mutiplytwonums
    cmpq $4, %r13
    je dividetwonums
    jmp main


addtwonums:
    add %rax, %r15
    call printint
    jmp main

subtwonums:
    sub %rax, %r15
    call printintminus
    jmp main

mutiplytwonums:
    imul %rax, %r15
    call printinttimes
    jmp main

dividetwonums:
    mov %rax, %r12         # 保存除数到r12
    mov %r14, %rax         # 将被除数放入rax
    cqo                    # 扩展符号位到rdx,准备有符号除法
    cmpq $0, %r12          # 检查除数是否为0
    je divisionbyzero
    idiv %r12              # 执行除法:rdx:rax / r12,商存rax,余数存rdx
    call printintdiv
    jmp main

divisionbyzero:
    mov $dividestr, %rdi
    mov %r14, %rsi         # 被除数
    mov $0, %rdx           # 除数(0)
    mov $0, %rcx           # 商设为0
    xor %rax, %rax
    call printf
    jmp main

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 03:34:54