【问题标题】:(LC3) Using characters within a string to point to the address of different subroutines?(LC3) 使用字符串中的字符来指向不同子程序的地址?
【发布时间】:2021-07-06 08:33:36
【问题描述】:

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

我有一个优化识别过程的想法——使用 x0-xf 的 .STRINGZ 作为各种字符索引——但我正在努力实现它。想法是使用counter = #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

【问题讨论】:

  • 您显示的代码并不能说明您要做什么,例如,您提到了一个循环,但没有编写一个;你也有 .FILL x30... 和 .STRINGZ "0"... 的重复数据结构,但没有说或显示你在使用这些时的想法。不过,我建议你在 C 中尝试一下,然后翻译它。这将帮助您制定循环及其变量和数据结构。也许您正在寻找数组的概念,可能是函数指针数组,或者在 switch/case 语句中使用的表的概念(另一种不同类型的数组)。
  • 抱歉,我对 Stack Overflow 很陌生,所以为了简洁起见,我不确定要编辑多少代码。我已经有一个功能循环来辨别价值是什么。我想我的问题很简单:是否可以使用存储在字符串中的字符来专门引用子程序的标签或地址?请记住,每个子例程将仅用于该特定字符条目。你对使用数组是绝对正确的。我的印象是 .STRINGZ 本质上创建了一个数组 (1/2)
  • 字符串的每个字符地址,我相信它们是按顺序存储在内存中的。我试图找出一种利用“数组”的方法,它基本上会使字符串中的每个字符都指向它各自的子例程。如果有帮助,我还可以发布更多我的程序!(2/2)

标签: string assembly memory subroutine lc3


【解决方案1】:

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

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

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

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

      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

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

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

您在这里看到我们实际上分支到表中,因为每个元素都是一个可执行指令。


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

【讨论】:

    猜你喜欢
    • 2012-04-23
    • 1970-01-01
    • 2021-07-15
    • 1970-01-01
    • 2021-06-28
    • 2015-10-10
    • 2016-02-02
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多