ARM 汇编中的 loRecursion 示例

夜光海狸鼠

有人能给我一个例子,说明如何在 ARM 汇编中仅使用此处列出的指令(用于视觉)来完成递归?

我正在尝试为类做一个递归斐波那契和阶乘函数。我知道递归是一个调用函数的函数,但我不知道如何在 ARM 中模拟它。

https://salmanarif.bitbucket.io/visual/supported_instructions.html

如果链接不起作用,我正在使用 visUAL,这些是我可以使用的唯一说明:

  • 移动
  • 移动网络
  • 不良反应
  • LDR
  • 添加
  • 模数转换器
  • 单板
  • RSB
  • 资源中心
  • 提高采收率
  • BIC
  • ORR
  • LSL
  • LSR
  • ASR
  • 回报率
  • 接收器
  • CMP
  • CMN
  • 尖沙咀
  • TEQ
  • LDR
  • 低密度脂蛋白
  • STM
  • BL
  • 充满
  • 结尾

这不会加载 R4 的旧值,因此每次函数调用自身时 R4 都会加倍。

    ;VisUAL initializess all registers to 0 except for R13/SP, which is -16777216

    MOV     R4, #0
    MOV     R5, #1

    MOV     r0, #4

    MOV     LR, #16             ;tells program to move to 4th instruction


FIB


    STMDB   SP!, {R4-R6, LR}    ;Stores necessary values on stack (PUSH command)
    LDR     R4, [SP]            ;Loads older value for R4 from memory
    ADD     R4, R4, R5          ;Adds R5 to R4
    STR     R4, [SP], #8        ;stores current value for R4 to memory
    MOV     R5, R4              ;Makes R5 = R4


    CMP     R4, #144            ;If R4 >= 144:
    BGE     POP                 ;Branch to POP

    MOV     PC, LR              ;Moves to STMDB(PUSH) statement

POP
    LDMIA   SP!, {R4-R6, LR}    ;Pops registers off stack
    END                         ;ends program
尼克JH

您需要使用堆栈、STMDB 和 LDMIA 指令。在具有“统一”符号的真正 ARM 工具上,它们还具有助记符 PUSH 和 POP。

斐波那契和阶乘并不是很好的例子,因为它们“不需要”递归。但让我们假装他们这样做。我会选择斐波那契,因为你没有 MUL 指令!?你想做这样的事情:

START
   MOV R0, #6
   BL FIB
   END ; pseudo-instruction to make your simulator terminate

FIB                                 ; int fib(int i) {
   STMDB SP!, {R4,R5,R6,LR}         ;   int n, tmp;
   MOV R4, R0                       ;   n = i;
   CMP R0, #2                       ;   if (i <= 2) {
   MOV R0, #1                       ;     return 1;
   BLE FIB_END                      ;   }
   SUB R0, R4, #2                   ;   i = n-2;
   BL FIB                           ;   i = fib(i);
   MOV R5, R0                       ;   tmp = i;
   SUB R0, R4, #1                   ;   i = n-1;
   BL FIB                           ;   i = fib(i);
   ADD R0, R0, R5                   ;   i = i + tmp;
FIB_END                             ;   return i;
   LDMIA SP!, {R4,R5,R6,PC}         ;  }

它应该以包含 fib(6) == 8 的 R0 终止。当然,这段代码非常低效,因为它重复调用 FIB 以获得相同的值。

STM 是必需的,因此您可以使用寄存器 r4、r5,因为另一个函数调用可以更改 r0-r3 和 LR。推LR和弹出PC就像B LR。如果您正在调用 C 代码,您应该推送偶数个寄存器以保持 SP 64 位对齐(我们在这里真的不需要这样做;忽略 R6)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章