向LMC输入三个数,从大到小输出?
Input three numbers into the LMC and output them largest to smallest?
所以,我已经设法解决了大部分问题,但是如果输入值递增,我只能从大到小输出? first = 10,second = 20,third = 30。如果值不同,我将如何正确输出? (例如,5、1、3?)
这是我目前拥有的:
INP
STA first
INP
STA second
INP
STA third
SUB first
BRP branch1
LDA second
STA third
branch1 LDA third
SUB second
BRP branch2
LDA first
STA third
branch2 LDA third
OUT
LDA first
SUB second
BRP branch3
LDA second
OUT
branch3 LDA first
OUT
HLT
first DAT
second DAT
third DAT
我建议你为此编写C或伪代码。它只会是一两行左右,这会让你理清思路。
您的 pseudo/C 代码将包含 if-then-else 语句。这是高级 C 中的 if-then-else 模式,然后在低级 C 中重复。当您翻译 if-then-else 语句时,请遵循以下模式:
if ( <condition> ) {
<then-part>
}
else {
<else-part>
}
请注意,then 部分和 else 部分中只有一个应该 运行。
相同的控制结构,if-then-else,在汇编语言的 if-goto-label 风格中:
if <condition> is false goto elsePart1;
<then-part>
goto endIf1;
elsePart1:
<else-part>
endIf1:
我们首先要注意标签不执行——处理器看不到它们,因为它们在生成机器代码时被汇编器删除了。处理器只能看到&执行机器码指令,标签没有机器码。
以下是 if-then-else 在 if-goto-label 中的工作方式:当条件为假时,它将跳过 then-部分到 运行 else-部分。但在条件为真时,它不会分支并因此执行 then-part。 then 部分执行后我们需要跳过 else 部分 这就是无条件分支和 endIf1:
标签的原因如果转到标签版本 。 (如果没有那个无条件分支,它会 运行 then 部分之后的 else 部分,这会很糟糕。)同样重要的是,在 if-then-else 语句之后,程序 运行是下一条语句,不管它的 then-part 还是 else-part 都被触发了。
如果您有多个 if-then-else 语句,只需为其标签使用不同的编号即可。嵌套的 if-then-else 仍应遵循此模式——建议先翻译外部的,然后再翻译内部的,但其他顺序也可以。它也可以按程序顺序完成,但这使得遵循这些简单的模式变得更加困难。
一些问题:
当你这样做时:
LDA second
STA third
...您丢失了 third
的原始输入,因此不可能仍然产生正确的输出。在您执行 STA
的其他地方也会发生同样的情况。相反,您可以考虑 swap 值。通常你需要一个临时变量(一个额外的 DAT
)。例如,如果您想将 second
与 third
交换,则:
LDA second
STA temp
LDA third
STA second
LDA temp
STA third
您从 first
和 third
之间的比较开始,当您检测到 first
大于 third
时,您复制 second
到 third
。奇怪的是,你决定在这一点上涉及 second
(对此你没有做出任何结论)。用 first
做点什么会更有意义。如果您将 swap first
与 third
那么您将得到 first
现在保证不大于 [=13] 的“不变量” =],无论您是 分支 到 branch1
还是从上一条指令到达该标签。这是对输入进行排序的第一步。
如果 BRP branch3
导致跳转至 branch3
,您最终将只有 2 个输出而不是 3 个。None 三个 OUT
指令应该被跳过。或者你应该添加更多的 OUT
指令,这样在每个执行路径中总是恰好有 3 个被执行。
这是更正后的脚本,您可以在此处运行:
#input: 3 1 2
INP
STA first
INP
STA second
INP
STA third
SUB first
BRP branch1
LDA first # don't deal with second, but with first
STA temp # use temp to perform swap first <--> third
LDA third
STA first
LDA temp
STA third
branch1 LDA third # at this point we know first <= third
SUB second
BRP branch2
LDA second # don't deal with first, but with second
STA temp # use temp to perform swap second <--> third
LDA third
STA second
LDA temp
STA third
branch2 LDA third # at this point we know first <= third && second <= third
OUT
LDA first
SUB second
BRP branch3
LDA second
OUT
LDA first # We cannot use branch3 here, as there we still output second
OUT
HLT
branch3 LDA first
OUT
LDA second
OUT
HLT
first DAT
second DAT
third DAT
temp DAT
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc@v0.816/lmc.js"></script>
所以,我已经设法解决了大部分问题,但是如果输入值递增,我只能从大到小输出? first = 10,second = 20,third = 30。如果值不同,我将如何正确输出? (例如,5、1、3?)
这是我目前拥有的:
INP
STA first
INP
STA second
INP
STA third
SUB first
BRP branch1
LDA second
STA third
branch1 LDA third
SUB second
BRP branch2
LDA first
STA third
branch2 LDA third
OUT
LDA first
SUB second
BRP branch3
LDA second
OUT
branch3 LDA first
OUT
HLT
first DAT
second DAT
third DAT
我建议你为此编写C或伪代码。它只会是一两行左右,这会让你理清思路。
您的 pseudo/C 代码将包含 if-then-else 语句。这是高级 C 中的 if-then-else 模式,然后在低级 C 中重复。当您翻译 if-then-else 语句时,请遵循以下模式:
if ( <condition> ) {
<then-part>
}
else {
<else-part>
}
请注意,then 部分和 else 部分中只有一个应该 运行。
相同的控制结构,if-then-else,在汇编语言的 if-goto-label 风格中:
if <condition> is false goto elsePart1;
<then-part>
goto endIf1;
elsePart1:
<else-part>
endIf1:
我们首先要注意标签不执行——处理器看不到它们,因为它们在生成机器代码时被汇编器删除了。处理器只能看到&执行机器码指令,标签没有机器码。
以下是 if-then-else 在 if-goto-label 中的工作方式:当条件为假时,它将跳过 then-部分到 运行 else-部分。但在条件为真时,它不会分支并因此执行 then-part。 then 部分执行后我们需要跳过 else 部分 这就是无条件分支和 endIf1:
标签的原因如果转到标签版本 。 (如果没有那个无条件分支,它会 运行 then 部分之后的 else 部分,这会很糟糕。)同样重要的是,在 if-then-else 语句之后,程序 运行是下一条语句,不管它的 then-part 还是 else-part 都被触发了。
如果您有多个 if-then-else 语句,只需为其标签使用不同的编号即可。嵌套的 if-then-else 仍应遵循此模式——建议先翻译外部的,然后再翻译内部的,但其他顺序也可以。它也可以按程序顺序完成,但这使得遵循这些简单的模式变得更加困难。
一些问题:
当你这样做时:
LDA second STA third
...您丢失了
third
的原始输入,因此不可能仍然产生正确的输出。在您执行STA
的其他地方也会发生同样的情况。相反,您可以考虑 swap 值。通常你需要一个临时变量(一个额外的DAT
)。例如,如果您想将second
与third
交换,则:LDA second STA temp LDA third STA second LDA temp STA third
您从
first
和third
之间的比较开始,当您检测到first
大于third
时,您复制second
到third
。奇怪的是,你决定在这一点上涉及second
(对此你没有做出任何结论)。用first
做点什么会更有意义。如果您将 swapfirst
与third
那么您将得到first
现在保证不大于 [=13] 的“不变量” =],无论您是 分支 到branch1
还是从上一条指令到达该标签。这是对输入进行排序的第一步。如果
BRP branch3
导致跳转至branch3
,您最终将只有 2 个输出而不是 3 个。None 三个OUT
指令应该被跳过。或者你应该添加更多的OUT
指令,这样在每个执行路径中总是恰好有 3 个被执行。
这是更正后的脚本,您可以在此处运行:
#input: 3 1 2
INP
STA first
INP
STA second
INP
STA third
SUB first
BRP branch1
LDA first # don't deal with second, but with first
STA temp # use temp to perform swap first <--> third
LDA third
STA first
LDA temp
STA third
branch1 LDA third # at this point we know first <= third
SUB second
BRP branch2
LDA second # don't deal with first, but with second
STA temp # use temp to perform swap second <--> third
LDA third
STA second
LDA temp
STA third
branch2 LDA third # at this point we know first <= third && second <= third
OUT
LDA first
SUB second
BRP branch3
LDA second
OUT
LDA first # We cannot use branch3 here, as there we still output second
OUT
HLT
branch3 LDA first
OUT
LDA second
OUT
HLT
first DAT
second DAT
third DAT
temp DAT
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc@v0.816/lmc.js"></script>