问题描述
我正在尝试在LMC中运行一个将任何数字转换为二进制的程序。
通常我只会使用除法,但由于Little Man Computer不允许除法或乘法,所以我不能这样做。我在这方面获得的最大成果只是一个简单的INP
。在这个阶段,我不知道如何开始循环,甚至不知道如何开始。
如何开始循环?我该如何阻止他们?我将需要一个重复循环,该循环将一个值减去直到达到1或0。这将实现我的目标,因为我可以直接将其输出。
例如:我输入33,它的输出为100 001。
我是一个初学者。我今天才拿起它,因此将其保持简单将不胜感激。
解决方法
您写道,对于33,输出应为100001。这可能不起作用(取决于LMC仿真器),因为第二个值可以在不带前置零的情况下输出,因此它将显示为1001。可以是令人困惑,因为它看起来很像您对输入9的期望。
我建议将每个二进制数字作为一个单独的数字输出:这样,您可以确保在输出中显示所有 个数字。
像这样对输入 n 进行编码的算法可能如下:
-
将 n 与512进行比较。如果不小于
a。输出1,然后从 n 中减去512,否则:
b。输出0
-
将 n 的值加倍,即将 n 添加到自身
-
再重复上述9次。递减以10开头的计数器,并在不设置负标志的情况下重复执行。
如何循环播放
因此,您以静态方式“开始”循环:在DAT
指令中设置计数器的初始值。在上述算法中,我们希望计数器从10开始:
COUNTER DAT 10
然后在需要循环时,递减计数器:
LDA COUNTER
SUB ONE
STA COUNTER
并且(像许多LMC程序一样),您需要一个常量ONE
:
ONE DAT 1
最后,要知道计数器是否未低于0,可以检查“负”标志。当出现负溢出时,这是一个可由SUB
设置的标志(请记住,LMC不能真正地存储负值,因此您仅可以使用该标志作为指示)。 BRP
指令(为肯定时分支)将使用该标志来决定是否跳转:
BRP LOOP
LOOP
应该是循环代码开始的位置的标签。
实施
请注意,在这种实际情况下,执行此循环不超过10次是没有用的,因为LMC中的输入不能超过999(二进制需要10位数字)。
这是上述算法的实现,还应注意,即使在首次执行后将程序计数器复位,计数器也将从其初始值开始:
#input:13
INP
STA NUM
LDA NINE
LOOP STA COUNTER
LDA NUM
COMPARE SUB POW_9
BRP BIT1
BIT0 LDA ZERO
OUT
BRA DOUBLE
BIT1 STA NUM ; Reduce number with 512
LDA ONE
OUT
DOUBLE LDA NUM
ADD NUM
STA NUM
LDA COUNTER
SUB ONE
BRP LOOP
ZERO HLT
POW_9 DAT 512
ONE DAT 1
NINE DAT 9
NUM DAT
COUNTER DAT
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc@v0.7/lmc.js"></script>
替代
还有其他几种方法可以完成此任务。例如,我们可以将10个二进制数字所需的2的幂硬编码为:1、2、4,...,512。
然后将输入值与最大输入值进行比较(2 9 = 512)。如果不小于1,则输出1位,否则输出0。如果为1,则从输入数字中减去2的幂。在两种情况下,都切换到先前的2的幂(2 8 )并重复此过程。重复此操作,直到完成2 0 的工作为止。
您可以尝试不带循环地实现此功能,但是您将拥有10倍的相同代码,而幂次为2。这对于在LMC的100个“邮箱”内存中存储甚至是一个挑战(但是,如果将输入限制为64,这样就可以工作,因此只需要6个二进制数字即可。
要通过循环(较少的代码)实现此目的,可以使用间接寻址技术。在LMC中,没有用于间接寻址的指令,但是可以使用自修改代码。
假设您具有如下实现的权力列表:
POW_9 DAT 512
POW_8 DAT 256
; ... etc
POW_0 DAT 1
然后,您将通过以下方式对POW_9与累加器进行比较:
COMPARE SUB POW_9
标签允许我们在此处存储不同的指令,以便下次执行该指令时,它将实际执行以下指令:
COMPARE SUB POW_8
可以通过以下操作来实现:
LDA COMPARE
ADD ONE
STA COMPARE
这有点棘手,因为将代码视为数据,这会修改代码。请注意,更改SUB POW_9
实际上是如何工作的,就像您引用数组中的元素并增加该数组中的索引一样。
您需要有一个停止条件,以便不要使代码引用DAT
列表中未包含的2的幂。为此,您可以将修改后的代码与引用最低功率2的固定代码段(也是SUB
,但从未执行)进行比较。
以下是此想法的实现:
#input:13
INP
STA NUM
LDA FIRST
LOOP STA COMPARE ; self-modifying code!
SUB LAST ; Compare with "SUB ZERO"
BRP ZERO
LDA NUM
COMPARE SUB POW_9 ; Indirect addressing
BRP BIT1
BIT0 LDA ZERO
OUT
BRA NEXT
BIT1 STA NUM ; Reduce number with power
LDA ONE
OUT
NEXT LDA COMPARE ; Change power of 2
ADD ONE
BRA LOOP
FIRST SUB POW_9 ; Never executed
LAST SUB ZERO ; Never executed
POW_9 DAT 512
POW_8 DAT 256
POW_7 DAT 128
POW_6 DAT 64
POW_5 DAT 32
POW_4 DAT 16
POW_3 DAT 8
POW_2 DAT 4
POW_1 DAT 2
ONE DAT 1
ZERO HLT
NUM DAT
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc@v0.7/lmc.js"></script>