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