Overflow problems with summing squares

倾然丶 夕夏残阳落幕 提交于 2019-12-24 18:22:37

问题


I'm tackling an assignment which asks us to:

Write a program in MIPS assembly which, given a memory address in $a0 to the first element of an array of n 32-bit unsigned numbers (n is stored in $a1), it should square each one of them and sum the squares. The 32 most significant bits should be returned on $v1, while the least significant ones on $v0.

Special returns (on v0):

  • Zero if the array has no elements (n = 0)
  • DEADBEEF (hex) = 3735928559 (dec) if the result can't fit in 64 bits.

What I've done so far: (the input is handled by separate, given to us code)

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

For input of small numbers (even in large arrays) the program works as intended. My problem is that when I input a large number (ie. 2000000000), during the multiplication the lo register overflows and flips to minus, which implies that everything stored in lo gets signed, while I want it to be unsigned in order to return to 0 and count upwards. Is there any workaround for this?

Thanks for your time.

PS: FYI, I'm using MARS for interpreting the code.

来源:https://stackoverflow.com/questions/49965565/overflow-problems-with-summing-squares

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!