Assembly 分支到ARM汇编中的不同子例程?

Assembly 分支到ARM汇编中的不同子例程?,assembly,arm,Assembly,Arm,假设我有以下汇编代码: subroutineA: ....some assembly code.... subroutineB: ....some assembly code.... subroutineC: ....some assembly code.... 现在,在另一个子例程中,我想构建一些随机分支到上面3个子例程之一的东西 比如: subroutineD: ....some code to randomly branch to either

假设我有以下汇编代码:

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 ....
ldr R4, =my_arr
ldr R5, [R4, R0]
如何在ARM汇编程序中有效地实现这一点

以下是我最终如何解决这个问题的,它可能有一天会帮助其他人(下面的伪代码):

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

我还有一些随机数生成器在汇编(LFSR)。假设我在
R0
中有随机数(当然,请确保随机数在0和子例程总数之间),然后我会执行如下操作:

subroutineD:
  ....some code to randomly branch to either 
       subroutineA, or subroutineB, or subroutineC ....
ldr R4, =my_arr
ldr R5, [R4, R0]
然后在
R5
中,我有随机子程序的地址。然后我可以简单地做:

blr R5

转到子例程。

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

 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第二版9.2.5多路分支中的开关类型语句

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

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

@OliverCharlesworth我想你的建议是,首先生成一个数字,然后进行比较,如果数字为1,则执行bl子程序a,如果数字为2,则执行bl子程序B,等等。但是如果我有很多子例程,这会变得非常低效吗?也许我不明白你在说什么?你可以用汇编语言做几乎完全相同的事情。创建一个函数地址数组,并根据随机数间接调用该数组中的一个函数。在汇编语言中,跳转表可能比大多数高级语言中的跳转表更简单。如果这个问题真的是关于“构建某些东西”的“某些代码”的特定实现,它可能应该这么说。@JJackJi#1规则更为具体-您清楚地理解您的目标,但您向我们提供了一个模糊的想法组合:“如何在汇编中实现RNG算法”是一个问题,“如何调用
rand()
from assembly code“是一个不同的问题,“如何最好地基于变量分派不同的函数调用”是第三个问题。前两个,一旦定义清楚,就很容易搜索(事实上,一个简单的线性同余生成器在C语言中非常容易,所以这将是一个很好的组装练习)。第三种方法需要更多的细节,例如所有函数都有相同的签名吗?@不象刚刚更新的那样,现在更好了吗?这不是编译器实现开关的唯一方法,但却是一种常见的方法。