我不太确定 OP 在这里想要什么。如果你真的想要:
move #2,X
jsr "routine(X)"
只是做
bsr routine2
如果您想在代码的某些部分决定是稍后调用routine1 还是routine2,我会将该地址加载到地址寄存器中并在需要时调用它(在大多数情况下,您不应该缺少地址寄存器——但您必须仔细跟踪您在代码的哪些部分使用了哪个寄存器)
; under some condition:
lea routine1(PC),a4
; under another condition:
lea routine2(PC),a4
; later:
jsr (a4)
如果您有一个变量(在内存中或在寄存器中)并且想要根据其值调用两个子例程之一,请执行以下分支:
tst.w d0 ; lets assume for d0==0 we call routine1, otherwise routine2
bne.s \callr2
bsr routine1
bra.s \continue
\callr2:
bsr routine2
\continue:
; more code
如果more code 只是一个rts,请将bne.s \callr2 替换为bne routine2,将bsr routine1 替换为bra routine1(即尾调用)。
第三种选择,如果您在d0 中有一系列值,并且您想根据该值分支到特定方法,那将是一个跳转表,可以这样实现(假设所有例程都是在 16 位地址范围内 - 您还需要验证 d0 不包含超出跳转表大小的值):
add.w d0,d0 ; multiply d0 by two
move.w jumptable(PC,d0.w),d0 ; d0 contains the offset relative to `jumptable`
jsr jumptable(PC,d0.w) ; do the actual function call
; more code -- if this is just a `rts` use `jmp` instead of `jsr`
; somewhere else:
jumptable:
dc.w routine0-jumptable, routine1-jumptable, routine2-jumptable, ...
如果另外,所有例程的大小完全相同(理想情况下是 2 的幂 - 可能在一些填充之后,或者在必要时使用一些蹦床),您也可以直接跳转到类似 PC+offset+d0*size_of_method 的内容:
lsl.w #4,d0 ; d0 = 16*d0
jsr routine0(PC,d0.w) ; PC = routine0+d0
; more code
routine0:
; exactly 16 bytes of code
routine1:
; exactly 16 bytes of code
routine2:
; exactly 16 bytes of code
routine3:
; (last method could be arbitrary long)