(LC3) 用字符串中的字符指向不同子程序的地址?

(LC3) Using characters within a string to point to the address of different subroutines?

我正在尝试用 LC3 程序集编写一个程序,该程序基本上采用用户输入的 1-4 个十六进制值,将它们存储到相应的标签中,然后识别这些值中的每一个是什么,以便通知程序跳转到哪个子程序(将有一个子程序十六进制字符 x0-xf)。我已经完成了用户输入部分。

我有一个优化识别过程的想法——使用 x0-xf 的 .STRINGZ 作为各种字符索引——但我正在努力实现它。这个想法是使用计数器 = #16 的循环,这样每次迭代都会从索引字符串中加载相应的字符,然后将该值与用户输入进行比较,如果值相等,则程序将跳转到对应于现在已知的用户输入标识的子例程。如果它们不相等,循环将重新开始。我的问题是:在循环完成并且值已知之后,我如何才能使用字符串中的特定字符指向它对应的相应标签或内存位置?可以想象,您也可以使用循环计数器来指向地址或标签,但从概念上讲它们非常相似。

.ORIG x3000
;-----------------------------------
;other code
;-----------------------------------
;values in these labels are for the sake of example.
CHAR1       .FILL x30
CHAR2       .FILL x31
CHAR3       .FILL x32
CHAR4       .FILL x33
SUB_RET     .FILL x0000 
;-----------------------------------
;**Question relevant section**
;-----------------------------------
CHAR_FIND   ST R7, SUB_RET
LEA R0, H_INDEX
;CHAR ID LOOP   
            RET
H_INDEX .STRINGZ "0123456789abcdef"         
;-----------------------------------
;CHARACTER SUBROUTINES (REMOVED SEVERAL FOR BREVITY)
;-----------------------------------
D_CHAR_0    ST R7, SUB_RET  
            ;REMOVED SUBROUTINE CONTENTS FOR BREVITY

            
D_CHAR_1    ST R7, SUB_RET          
            ;REMOVED SUBROUTINE CONTENTS FOR BREVITY


D_CHAR_2    ST R7, SUB_RET  
            ;REMOVED SUBROUTINE CONTENTS FOR BREVITY

D_CHAR_3    ST R7, SUB_RET  
            ;REMOVED SUBROUTINE CONTENTS FOR BREVITY

字符串中的字符一旦被提取为字符,就只是一个值。那么,我们可以使用该值来索引数组吗?是的,当然。

我们可以有一个指向代码的指针数组吗?也是的,这是一个数据数组,其元素值是指针(指向代码中的标签,可能是函数)。

DTBL, .FILL hello         ; data pointer to code
      .FILL world         ; data pointer to code
      .FILL there         ; data pointer to code
      ...

其中 hello 是函数标签,world 是函数标签。我们将按如下方式使用它(假设您的索引在 R1 中,并且已知它在 table 大小的限制范围内):

      LEA R0, DTBL        ; point to start of data table / array
      ADD R0, R0, R1      ; points to proper element in table
      LDR R0, R0, #0      ; load data pointer element from table
      JSRR R0             ; indirect function call thru pointer

或者如果代码标签不是函数,而只是代码中的标签都在同一个函数中,那么 JMP 而不是 JSR

      LEA R0, DTBL        ; point to start of data table / array
      ADD R0, R0, R1      ; points to proper element in table
      LDR R0, R0, #0      ; load data pointer element from table
      JMP R0              ; indirect jump thru pointer

此外,您可以创建一个“代码数组”,如果您愿意,可以创建一个 table,其中数组元素是 executable 指令,通常是 BR 指令。所以,不是索引到数据中 array 执行间接分支,我们可以索引到代码数组 -- 通过索引跳转到代码数组。

CTBL, BR hello            ; code instruction element
      BR world            ; code instruction element
      BR there            ; code instruction element
      ...

哪个可以更直接地用作分支目标,而不是将元素作为指针加载:

      LEA R0, CTBL        ; points to start of code table / array
      ADD R0, R0, R1      ; points to proper element from table
      JSRR R0 ; or JMP R0 ; indirect function call (or jmp) directly into the table

你看这里我们实际上分支到 table 因为每个元素都是一个 executable 指令。


这些是编译器用于 switch 语句的一些结构,特别是当 case 值密集且连续时。当它们不是时,编译器将尝试识别此类范围的不同组,使用普通的 if-then-else 结构来分隔组。