Assembly 平方和溢出问题

Assembly 平方和溢出问题,assembly,mips,Assembly,Mips,我正在处理一项任务,要求我们: 在MIPS assembly中编写一个程序,该程序在为n个32位无符号数字(n存储在$a1中)数组的第一个元素指定$a0中的内存地址时,应将每个数字平方并求和。32个最高有效位应在$v1上返回,而最低有效位应在$v0上返回 特殊退货(在v0上): 如果数组没有元素(n=0),则为零 如果结果不能放入64位,则DEADBEEF(十六进制)=3735928559(十二进制) 到目前为止我所做的:(输入由单独的、给定给我们的代码处理) 对于小数字的输入(即使在大数组

我正在处理一项任务,要求我们:

在MIPS assembly中编写一个程序,该程序在为n个32位无符号数字(n存储在
$a1
中)数组的第一个元素指定
$a0
中的内存地址时,应将每个数字平方并求和。32个最高有效位应在
$v1
上返回,而最低有效位应在
$v0
上返回

特殊退货(在
v0
上):

  • 如果数组没有元素(n=0),则为零
  • 如果结果不能放入64位,则DEADBEEF(十六进制)=3735928559(十二进制)
到目前为止我所做的:(输入由单独的、给定给我们的代码处理)

对于小数字的输入(即使在大数组中),该程序按预期工作。我的问题是,当我输入一个大数字(即2000000)时,在乘法过程中,
lo
寄存器溢出并翻转为负数,这意味着存储在
lo
中的所有内容都会被签名,而我希望它不被签名,以便返回到0并向上计数。有什么解决办法吗

谢谢你抽出时间


PS:仅供参考,我使用MARS解释代码。

您使用的是无符号数字,因此高位不是符号位。签名与未签名仅为解释问题;告诉调试器不带符号地打印它,或者忽略伪带符号的十进制值并查看十六进制。这是个问题。MARS似乎强制将结果解释为带符号,因为在组装时它抛出算术溢出异常,我找不到任何类似于更改此解释的选项。Lo没有溢出。看起来就像是这样,0x9D900000设置了高位。不要被调试器或仿真器告诉您的内容弄糊涂,如果它有将寄存器值显示为unsigned的选项,那么您会喜欢使用它。如果没有,则只需验证最终结果。@lightspot21:您是否使用
add
而不是
addu
?(您的代码不在您的问题中;请将其放在代码块中,以便人们可以查看)。MIPS具有特殊的签名添加指令,可捕获签名溢出。不要在
=2^31
的未签名数据上使用它们
addu
/
addui
是正常的包装指令,而不是陷阱指令。术语:除非您有MARS错误或限制,否则在组装时它不会溢出;当你在模拟器中运行时。(此外,MARS不会解释asm源代码;它会在其MIPS模拟器中汇编并运行MIPS机器代码)。
squaredSum:
            beq     $t5, $zero, getRetAddr  # if $t5 (caller's ret. addr.) is zero (ie. first time the function is called, then get the caller's ret. addr.)  
            move    $t0, $a1                # $t0: array size (we want to turn it into bytes)
            sll     $t0, $t0, 2             # multiply array size by 4, so we get the total number of bytes (2 left bitwise shifts)
            beq     $t1, $t0, sumExit       # if offset ($t1) = bytes, then end of array, so we terminate (jump to "exit" label)
            add     $t2, $t1, $a0           # $t2: address from which we start reading (base + offset)
            lw      $t3, 0($t2)             # $t3: the number to be squared is loaded here
            mult    $t3, $t3                # multiply $t3 with itself (square), result of multiplication goes to internal registers Hi and Lo
            mfhi    $t8                     # load HI's contents into $t8
            mflo    $t9                     # load LO's contents into $t9
            addi    $t1, $t1, 4             # add 4 to offset (move to next element, since numbers are 32bit)
            jal     adduover                # call adduover to sum the newly found square
            b       squaredSum              # go back to the beginning of the loop

adduover:
            add    $t7, $t7, $t9            # add Lo to $t7
            add    $t6, $t6, $t8            # add Hi to $t6
            blt    $t7, $t9, correction     # if total sum of Lo is lower than Lo before summation (32bit overflow) then jump to label "correction"
            blt    $t6, $t8, overflow       # if total sum of Hi is lower than before summation (64bit overflow) then jump to label "overflow"s
            jr     $ra

correction:
            addi    $t8, $t8, 1             # add 1 to the most significant bits (we made a full circle)
            jr      $ra                     # continue with adduover

overflow:
            li      $v0, 3735928559         # return as result (0x00000000DEADBEEF) in case of 64-bit overflow
            jr      $ra                     # continue with adduover

getRetAddr:
            move    $t5, $ra                # get the return addr. of squareSum's caller, because it gets overwritten during execution
            j       squaredSum              # continue with squaredSum

sumExit:
            move $v0, $t9                   # send least significant 32 bits to $v0 (exercise output)
            move $v1, $t8                   # same as above for most significant

                jr   $t5                        # return to squaredsum's caller's address