在 MIPS 中使用 addu 检测溢出

Detecting for Overflow using addu in MIPS

提问人:TJream 提问时间:10/23/2023 最后编辑:Peter CordesTJream 更新时间:10/24/2023 访问量:41

问:

我正在努力实现MIPS中的溢出并使用addu检测溢出并抛出错误。

这是针对学校作业的。我们得到的代码是一个非常基本的银行分类账。账本要求用户输入,如果为正数,则添加到余额中,如果为负数,则从余额中减去。我已经改进了它,可以根据分配检测非整数输入,现在我需要能够检测溢出并抛出错误消息,并且在检测到溢出时不更改余额(然后重新提示交易)。我想到这里,因为这只是加法,如果符号相同并导致相反的符号,那么就会溢出。我还认为,如果迹象相反,那么就不会发生溢出。

目前,它似乎直接跳过了我的溢出检测,因此它可以工作,但没有检测到分配所需的溢出。关于我做错了什么有什么建议吗?

这是我代码的相关部分:

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
程序集 MIPS 加法 integer-overflow mars-simulator

评论


答:

0赞 Erik Eidt 10/24/2023 #1

你能解释一下你在这里想做什么吗?

    addu    $s2, $s0, $t6       #### set temporary balance to initial balance
    addu    $s2, $s0, $s1       # add transaction amount to the temporary Balance

?

这两个指令放在一起没有意义。第二个在不使用第一个结果的情况下擦除/重置。$s2


您使用的无符号比较小于 0 的直接值 — 根据无符号数字的定义,这将始终产生 false,因为没有无符号数字小于零。换句话说,负数不是无符号数字可能的属性。

如果您想知道该数字是否为负数,请改用有符号比较。

仅供参考,您还可以使用移位来提取或复制符号位,因此通过使用 31 的算术移位,获得 -1 或 0,并使用逻辑移位 31 获得 1 或 0。


从根本上说,你正在处理有符号的整数,所以你所有的比较操作都应该有符号,除非你真的知道那里的某个地方有什么不同的东西。

但是,您说得对,您需要进行无符号加法和/或减法以避免处理器的自动有符号溢出检测,因为如果您点击它,它将终止您的程序。当没有溢出时,无符号加法将产生与有符号加法相同的数字、相同的数值、相同的位模式,因此,这是有效的。— 如果有溢出,您可以在您思考时检测到它,例如在添加之后。

但是,为了有意义,需要使用有符号算术来进行比较,并且这些有符号比较(与有符号加法/减法不同)不会有遇到处理器溢出陷阱的风险。

评论

0赞 TJream 10/24/2023
第一个 addu lign 是我错过的一个错别字。感谢您的注意!幸运的是,它没有破坏我的代码,所以我没有注意到它。嗯,好吧,我没有意识到将它们与零进行比较是行不通的。很抱歉,我的教授基本上只是在课堂上发布 Youtube 视频,这些视频涵盖了我们应该学习的部分但不是全部内容,然后将作业转交给我们,所以我真的很难理解 MIPS 的语法和操作与其他语言相比。切换到有符号的比较有效!!!谢谢!!!!