嗨,我需要帮助在MIPS编码。我必须找到n输入的地板平方根。我有C版本的代码。
uint32_t isqrt(uint32_t n) {
if(n<2) return n;
uint32_t s = isqrt(n >> 2) << 1;
uint32_t l = s + 1;
if (l * l > n)
return s;
else
return l;
}
显然它会自己递归。
现在我的函数看起来像这样。我不确定我做错了什么
#isqrt
isqrt:
#prologue
subu $sp, $sp, 12
sw $ra, 8($sp)
sw $s0, 4($sp)
sw $s1, 0($sp)
#if(n<2) n Branch if Greater Than 2
blt $a0, 2, lt2 #if(n<2) return n;
#else uint32_t small = isqrt(n >> 2) << 1;
srl $s0, $a0, 2 # small = isqrt(n >> 2)
jal isqrt
sll $s0, $s0, 1 # then << 1
add $s1, $s0, 1 # large = small + 1
li $s3, 0
mul $s3, $s1, $s1 # large = large * large\
#if large * large > n return small else return large
bgt $s3, $s0, small # if l * l > n return small
move $v0, $t1 # else return large
lt2:
move $v0, $a0;
j end
small:
move $v0, $s0
j end
end:
lw $ra, 8($sp)
lw $s0, 4($sp)
lw $s1, 0($sp)
addi $sp, $sp, 12
jr $ra
1条答案
按热度按时间bf1o4zei1#
很好的努力,但是很多很多错误。建议尝试一种更有方法论的方法。检查您对寄存器的选择,您的寄存器编号,以及序言/尾声代码,以便正确处理各种寄存器类型。
if (n>=2) return n;
-与C代码完全相反。isqrt
需要$a0
中的形参,但该代码传递的是$t0
中的实参,因此存在不匹配。isqrt
在$v0
中提供返回值,但在递归调用时,期望它已经在$t0
中提供,这是另一个不匹配。$s0
,但无法确保其值按应有的方式被调用保留。下面的代码:
2>>2
,这与C程式码中的n>>2
明显不同。下面的代码:
return l;
的地方执行return l*l;
我建议从分析哪些寄存器用于哪些变量开始-此分析需要检查(递归)函数调用。最初在C版本上开始分析。当您完成该分析时,你将得到所有C变量的寄存器号的Map。2然后编写序言/尾声来根据需要处理这些寄存器。然后将C代码逐行翻译成汇编代码,注意哪些变量在哪些寄存器中,以及您试图在汇编代码中重新创建哪些表达式。