分支到ARM程序集中的不同子程序?

时间:2014-09-29 22:38:53

标签: assembly arm

说我有以下汇编代码:

subroutineA:
   ....some assembly code....

subroutineB:
   ....some assembly code....

subroutineC:
   ....some assembly code....

现在,在另一个子例程中,我想构建一些随机分支到上面3个子例程之一的东西。

类似的东西:

subroutineD:
  ....some code to randomly branch to either 
       subroutineA, or subroutineB, or subroutineC ....

如何在ARM汇编程序中有效地执行此操作?

以下是我最终解决问题的方法,并且有一天它可能对其他人有帮助(下面的伪代码):

我在Assembly中声明了一个数组来存储所有子程序标签(它们的内存地址):

.global my_arr
my_arr:
    .long subroutineA
    .long subroutineB  
    .long subroutineC
    .......

我在Assembly(LFSR)中也有一些随机数生成器。假设我在R0中有随机数(当然,确保0和子程序总数之间的随机数),那么我会做类似的事情:

ldr R4, =my_arr
ldr R5, [R4, R0]

然后在R5中,我有随机子程序的地址。然后我可以简单地做:

blr R5

转到子程序。

1 个答案:

答案 0 :(得分:1)

您可以有效地实现这样的跳转表,

 adr lr, return
 cmp r0, #3
 ldrlo pc, [pc, r0, lsl #2] @ pc is 8 bytes ahead
 b  error                   @ also functions as padding
.long subroutineA
.long subroutineB  
.long subroutineC
return:
 @ one of three routines finished here.
...
error:
 @ random out of array range.

这非常通用。 David Seal提供了一种在ARM ARM第二版 9.2.5 Multi-Way branch 中实现switch类型语句的好方法,

 cmp   r0,#max
 addlo pc, pc, r0, LSL #routineSizeLog2
 b     outOfRange
index0:
 ...
index1:
 ...
index2:
 ...

编译器通常会执行我的第一个版本(函数指针类型),但不需要保存lr来实现切换。通常case语句不是那么线性。但是,许多人使用David Seal的方法在汇编程序中创建中断处理程序等。