In calling function:
Load the number to be squared into $a0
jal root
root:
Initialize $t0 = n, $t1 = i = 0, $t2 = x = n = $a0, $t3 = n/2
Loop:
Divide n/x
Add x to n/x
Divide (x + n/x) by 2
Check if $t1 < $t3
If it is, branch back to loop
Else, move x into return register $v0
int isqrt(int num) {
int ret = 0;
int bit = 1 << 30; // The second-to-top bit is set
// "bit" starts at the highest power of four <= the argument.
while (num < bit) {
bit >>= 2;
}
while (bit != 0) {
if (num < ret + bit) {
ret >>= 1;
} else {
num -= ret + bit;
ret = (ret >> 1) + bit;
}
bit >>= 2;
}
return ret;
}
以下是生成的MIPS代码:
isqrt:
# v0 - return / root
# t0 - bit
# t1 - num
# t2,t3 - temps
move $v0, $zero # initalize return
move $t1, $a0 # move a0 to t1
addi $t0, $zero, 1
sll $t0, $t0, 30 # shift to second-to-top bit
isqrt_bit:
slt $t2, $t1, $t0 # num < bit
beq $t2, $zero, isqrt_loop
srl $t0, $t0, 2 # bit >> 2
j isqrt_bit
isqrt_loop:
beq $t0, $zero, isqrt_return
add $t3, $v0, $t0 # t3 = return + bit
slt $t2, $t1, $t3
beq $t2, $zero, isqrt_else
srl $v0, $v0, 1 # return >> 1
j isqrt_loop_end
isqrt_else:
sub $t1, $t1, $t3 # num -= return + bit
srl $v0, $v0, 1 # return >> 1
add $v0, $v0, $t0 # return + bit
isqrt_loop_end:
srl $t0, $t0, 2 # bit >> 2
j isqrt_loop
isqrt_return:
jr $ra
mov eax, 9513135 ; eax = number to take square root of
mov ebx, eax ; make a copy of eax in ebx
loopIt :
sub ebx, count ; count starts as 1, 3, 5, 7, 9
inc count ; count = even
inc count ; count = odd
inc sqrt ; gives sqrt value
mov eax, sqrt
cmp ebx, 0
js timetoReturn ; return value if signed num, aka goes over zero
jnz loopIt
timetoReturn :
mov reg, eax ; just outputting the value
8条答案
按热度按时间8mmmxcuj1#
我们可以使用像提交的for this question这样的算法,并根据需要进行调整。在进入MIPS之前,让我们看看C中的实现:
sqroot(n)
函数将计算与n
的平方根的下限相等的整数。所以如果你调用sqroot(225)
,你会得到15,但是sqroot(15)
会返回3而不是3.87298。从C代码中,我们可以概述MIPS代码的外观:
请注意:
1.确保根据需要推送和弹出堆栈。我为了简单起见把它省略了。
1.当除以2的幂时,可以使用srl指令。
1.有关MIPS指令的说明和其他信息,请参阅click here。
huwehgph2#
我发现牛顿的方法
x = (x + n/x) / 2
在只处理整数时不能令人满意,因为终止条件很难精确计算。n/2
只是一个猜测,并且几乎总是比必要的迭代次数更多。牛顿的方法是 * 二次收敛 *,并且不是正比于n
,而是sqrt(n)
。另一个建议,“不断重复直到x停止变化”也不起作用,因为对于非完美正方形x
将在根的下限和上限之间交替-因为整数数学,当x
略小于或略大于sqrt(n)
时,项n/x
将交替。我从wikipedia上取了一个逐位根计算方法,并创建了一个MIPS版本。它不会受到低效率(
n/2
)或模糊性(floor(sqrt(n))
或ceil(sqrt(n))
)的影响。可扩展的方法可以更有效地返回结果,但假设查找表不可用,这是一个很好的可靠方法。首先,我将C示例转换为仅使用小于(
<
)比较,因为MIPS仅提供设置小于slt
比较指令。以下是生成的MIPS代码:
您可以像其他MIPS过程一样调用它:
此过程始终为 * 正参数 * 返回
$v0 = floor(sqrt($a0))
。注意:代码会因为 * 负数参数 * 而进入无限循环。在调用此过程之前对输入进行清理。
js5cn81o3#
它不是在MIPS中,但仍然是组装。我发现的基本算法是基于这样一个事实,即前n个奇数加在一起= n^2。
所以如果你利用这一点,通过颠倒这个过程,从你想要的数字中减去平方根,你可以循环得到精确的答案,或者近似值。我相信它的根+1非完美的平方。
这个想法是,你循环的次数是n,这是你的平方根。
希望这对你有帮助。
zbdgwd5y4#
你可以尝试这个算法,它给出的整数小于或等于你的数字的平方根。
假设你想要
n
的平方根。然后重复以下计算:x = (x + n/x) / 2
选择
x = n
开始,并不断重复,直到x停止变化。hjzp0vay5#
这里有一个简单易懂的算法,用于计算正整数平方根的下限,在C中:
它与okstory的答案基于相同的原则,只是方式略有不同。
理论:递增的奇数被添加到partialSum,只要partialSum小于操作数。该结果等于奇数的数量相加以产生partialSum。
xoefb8l86#
你们都错了
你可以使用sqrt.s或sqrt.d汇编代码!(ex)平方米$12,$13
不要浪费你的时间来实现这些功能。
vmdwslir7#
如果你想计算一个整数的平方根,你首先需要将整数转换为浮点数。假设你想取平方根的数字存储在$t1中,那么它到浮点数的转换如下所示
现在您可以使用sqrt.s函数计算平方根。
所以现在$f1将保存存储在$t1中的整数的平方根
zqdjd7g98#
下面是MIPS 32中的一个过程/函数,用于查找整数的平方根。