assembly 平方根MIPS程序集

fnatzsnv  于 2022-11-30  发布在  其他
关注(0)|答案(1)|浏览(172)

嗨,我需要帮助在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
bf1o4zei

bf1o4zei1#

很好的努力,但是很多很多错误。建议尝试一种更有方法论的方法。检查您对寄存器的选择,您的寄存器编号,以及序言/尾声代码,以便正确处理各种寄存器类型。

  • 该代码执行if (n>=2) return n;-与C代码完全相反。
  • 被调用的函数isqrt需要$a0中的形参,但该代码传递的是$t0中的实参,因此存在不匹配。
  • 被调用的函数isqrt$v0中提供返回值,但在递归调用时,期望它已经在$t0中提供,这是另一个不匹配。
  • 该函数使用$s0,但无法确保其值按应有的方式被调用保留。

下面的代码:

li      $t0, 2        # small = isqrt(n >> 2) << 1
srl     $t0, $t0, 2
  • 会产生2>>2,这与C程式码中的n>>2明显不同。

下面的代码:

equal:
move $v0, $t1
j end
  • 在C代码需要return l;的地方执行return l*l;

我建议从分析哪些寄存器用于哪些变量开始-此分析需要检查(递归)函数调用。最初在C版本上开始分析。当您完成该分析时,你将得到所有C变量的寄存器号的Map。2然后编写序言/尾声来根据需要处理这些寄存器。然后将C代码逐行翻译成汇编代码,注意哪些变量在哪些寄存器中,以及您试图在汇编代码中重新创建哪些表达式。

相关问题