通过动态值调用子例程

问题描述

我对于68k还是很陌生,我想知道是否可以通过内存中的值调用特定的子例程。

代码示例:

X: dc.w 0

routine1: 
code
rts

routine2:
more code
rts

代码中的某处类似:

move.w #2,X
JSR routine(X)

要执行例程2,或者将move.w #1,X用于例程1

我不知道,也找不到任何示例,我的猜测是制作一个包含例程的标签,然后使用地址寄存器跳转到特定偏移量,但是不知道如何。

欢迎任何帮助!

解决方法

您正在寻找一个间接 JSR,该JSR在从地址数组中加载寄存器后将目标地址存储在寄存器中。 (自从我做过m68k以来已经有很长时间了,但是这些是您在指令集参考中寻找的关键字和概念。)更新:请参阅@chtz的注释。

查询将不会按名称进行,您必须在某个地方使用dc.l routine1,routine2来制作32位函数指针的表。

(除非两个/所有例程的长度都相同,并且您使用某些ALU指令而不是索引到内存中的数组中,而是在诸如routine1 + <constant> * index之类的寄存器中计算跳转目标。JSR的寻址模式可以是计算的一部分;例如jsr 4(a3)设置PC = A3 + 4)。

,

我不太确定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(即尾注)。 / p>

第三种选择,如果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)
,

这就是我最终将Peter Corder解决方案与一些外部建议结合起来的方法:

  TIMELINE:       DC.L __BLOCK_0,__BLOCK_1,__BLOCK_1
    DC.L __BLOCK_2,__BLOCK_2
    DC.L __BLOCK_2,__BLOCK_3 ... etc


 __BLOCK_0:
   ; SOME CODE
   RTS

-在主循环中-

MOVE.W  P61_LAST_POS,D5
LEA TIMELINE,A3
MULU.W  #4,D5     ; OFFSET IN BYTES
MOVE.L  (A3,D5),A4
JSR (A4)        ; EXECUTE SUBROUTINE BLOCK#

其中P61_LAST_POS是增量索引,它随时间变化。

通过这种方式,我只需编辑LUT“时间轴”即可控制在任何给定点执行的操作。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...