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

使用MIPS的addu指令实现溢出检测遇到问题求助

MIPS银行账本程序溢出检测问题排查

这是一项学校作业,我们拿到了一个基础银行账本程序,该程序会请求用户输入,若输入为正数则增加余额,为负数则减少余额。我已按作业要求完成了非整数输入的检测,现在需要实现溢出检测:当检测到溢出时抛出错误信息,不修改余额并重新提示交易。

我认为对于加法操作,若两个操作数符号相同但结果符号相反则发生溢出,若符号相反则不会溢出。但目前我的溢出检测逻辑似乎被直接跳过,程序能运行但无法按要求检测溢出,请问我哪里出错了?

相关代码

loopB:
    li  $s1, 0          #### reset $s1
    add $s1, $zero, $t3     #### load integer value into $s1
    beqz    $s1, done       # If $s1 equals zero, branch to done
    li  $s2, 0          #### initialize $s2 for temporary balance
    addu    $s2, $s0, $t6       #### set temporary balance to initial balance
    addu    $s2, $s0, $s1       # add transaction amount to the temporary Balance

oTest:
    sltiu   $t6, $s0, 0     #### if $t6 == 1 then number is negative
    sltiu   $t7, $s1, 0     #### if $t7 == 1 then number is negative
    
    bne $t6, $t7, LoopC     #### if opposite signs then no overflow
    
    sltiu   $t8, $s2, 0     #### if $t8 == 1 then the number is negative
    
    and $t9, $t6, $t7       #### if $t9 == 1 then $t6 and $t7 are both negative
    
    bne     $t9, $t8, over      #### if $t9 and $t8 are not both negative, then overflow has occured
    
    sgtu    $t6, $s0, $zero     #### if $t6 == 1 then number is positive
    sgtu    $t7, $s0, $zero     #### if $t7 == 1 then number is positive
    sgtu    $t8, $s0, $zero     #### if $t8 == 1 then number is positive
    
    and $t9, $t6, $t7       #### if $t9 == 1 then $t6 and $t7 are both positive
    
    bne $t9, $t8, over      #### if $t8 and $t9 are not equal then overflow has occured

LoopC:
    addu    $s0, $s0, $s1       #### add transaction to balance
    li  $v0, 4          # system call code for print_string
    la  $a0, tabs       # load address of tabs into $a0
    syscall             # used to space over to the Balance column
    
    li  $v0, 1          # system call code for print_integer
    move    $a0, $s0        # move Bank Balance value to $a0 
    syscall             # print Bank Balance
    
    b   loop            # branch to loop
    
over:
    li  $v0, 4          #### system call code for print_string
    la  $a0, oMsg       #### load address of msg. into $a0
    syscall             #### print the string
    
    li  $s2, 0          #### reset $s2
    
    li  $v0, 1          #### system call code for print_integer
    move    $a0, $s0        #### move Bank Balance value to $a0 
    syscall             #### print Bank Balance
    
    b   loop            # branch to loop

问题排查与修复

1. 临时余额计算错误

在loopB段,你先执行addu $s2, $s0, $t6,紧接着又执行addu $s2, $s0, $s1,这不仅会覆盖之前的赋值,而且$t6此时是未初始化的垃圾值,完全没有意义。正确做法是删掉第一行错误的赋值,只保留addu $s2, $s0, $s1来计算临时余额。

2. 溢出检测逻辑冗余且无效

当你完成同号判断后,后续重新给$t6、$t7、$t8赋值为sgtu $s0, $zero,这三个寄存器全部被设置为余额$s0的正负判断,直接覆盖了之前的操作数和结果符号信息,导致后面的检测代码完全失效。这部分冗余代码必须删除。

实际上,当两数同号时,只需要判断结果符号是否与操作数一致:

  • 若两数都是负数,结果应为负数,若结果为正则溢出;
  • 若两数都是正数,结果应为正数,若结果为负则溢出。

3. 指令使用错误

sgtu是无符号数的大于判断,而你需要判断的是有符号数的正负,应该用slt(判断是否小于0,即负数)或sgt(判断是否大于0,即正数),否则会把最高位为1的无符号数(对应有符号的负数)误判为正数。

修复后的关键代码

loopB:
    li  $s1, 0          #### reset $s1
    add $s1, $zero, $t3     #### load integer value into $s1
    beqz    $s1, done       # If $s1 equals zero, branch to done
    li  $s2, 0          #### initialize $s2 for temporary balance
    addu    $s2, $s0, $s1       # 仅保留这行,计算临时余额

oTest:
    slt     $t6, $s0, 0     #### $t6=1 表示余额$s0是负数
    slt     $t7, $s1, 0     #### $t7=1 表示交易金额$s1是负数
    
    bne $t6, $t7, LoopC     #### 符号相反,无溢出,跳转到更新余额
    
    slt     $t8, $s2, 0     #### $t8=1 表示计算结果是负数
    
    # 检测两数均为负数但结果为正的溢出情况
    and $t9, $t6, $t7       
    bne     $t9, $t8, over  
    
    # 检测两数均为正数但结果为负的溢出情况
    nor $t9, $t6, $zero     # 取反$t6(此时$t6=0,取反后为1)
    nor $t10, $t7, $zero    # 取反$t7(此时$t7=0,取反后为1)
    and $t9, $t9, $t10      # $t9=1 表示两数都是正数
    sgt $t11, $s2, $zero    # $t11=1 表示结果是正数
    bne     $t9, $t11, over 

LoopC:
    addu    $s0, $s0, $s1       
    li  $v0, 4          
    la  $a0, tabs       
    syscall             
    li  $v0, 1          
    move    $a0, $s0        
    syscall             
    b   loop            

over:
    li  $v0, 4          
    la  $a0, oMsg       
    syscall             
    li  $s2, 0          
    li  $v0, 1          
    move    $a0, $s0        
    syscall             
    b   loop            

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 18:47:35