【发布时间】:2018-04-03 16:52:12
【问题描述】:
需要将以下C代码转换成ARM汇编子程序:
int power(int x, unsigned int n)
{
int y;
if (n == 0)
return 1;
if (n & 1)
return x * power(x, n - 1);
else
{ y = power(x, n >> 1);
return y * y;
}
}
这是我目前所拥有的,但无法弄清楚如何让链接寄存器在每次返回后递增(不断循环回到同一点)
pow CMP r0, #0
MOVEQ r0, #1
BXEQ lr
TST r0, #1
BEQ skip
SUB r0, r0, #1
BL pow
MUL r0, r1, r0
BX lr
skip LSR r0, #1
BL pow
MUL r3, r0, r3
BX lr
【问题讨论】:
-
递归函数需要一些堆栈使用...
-
链接寄存器只有一个(把它想象成高级语言中的全局变量),即第一个子程序调用将耗尽它的存储潜力。对于进一步的子例程调用,您必须首先通过将链接寄存器值复制到其他存储中来“清空”它,然后调用子例程(它将用新的链接寄存器值替换),然后恢复以前的值。由于递归,可能的调用深度是无限的,因此您需要动态存储这些链接寄存器值。通常“堆栈内存”概念用于此类任务,请阅读一些教程。
-
您还必须存储/恢复本地使用的任何其他寄存器值,因此递归子调用不会破坏您当前的值。通过代码的智能重新排列,您通常可以最小化需要保留的本地值 = 最小化每个嵌套调用的存储总量,提高最大深度的可能限制(受可用堆栈内存量的限制)。使用
power函数,您无需担心最大深度(如果n是32 位,则32 是最大深度,即使您不小心使用它也应该适合堆栈)。 -
@EugeneSh。实现这一点的明智方法是尾递归,它不需要多个堆栈帧,并且可以在默认 ARM 调用约定中仅使用调用者保存的寄存器来完成。
-
@EOF 那将是迭代的。