string - (LC3) 使用字符串中的字符来指向不同子程序的地址?
问题描述
我正在尝试在 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
解决方案
字符串中的字符一旦提取为字符,就只是一个值。那么,我们可以使用该值来索引数组吗?是的当然。
我们可以有一个指向代码的指针数组吗?也是的,这是一个数据数组,其元素值是指针(指向代码中的标签,可能是函数)。
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 构造来分隔这些组。
推荐阅读
- angular - 角度中的@observable 前缀
- python - 显示来自相关表的数据 (Django)
- python - 我不想单击输入字段来输入数据。可以这样做吗?
- xml - Xpath:紧跟在元素之后的第一个字母/字符串
- html - BootstrapVue - 未定义属性或方法“数据”......使用范围插槽时
- javascript - 如何根据同一 WordPress 页面上的标题类名称更改 2 个表格行背景颜色
- java - 如何在java中表示这个数学函数
- python - 需要将给定的输出转换为列表
- visual-studio - 以全局方式在 Visual Studio 中设置 OpenCV
- ios - 来自应用商店的 React Native 应用程序中的 console.log 语句会发生什么?