2

所以,我已经设法解决了大部分问题,但是如果输入值上升,我只能从最大输出到最小?第一个 = 10,第二个 = 20,第三个 = 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
4

2 回答 2

2

一些问题:

  • 当你这样做时:

    LDA second
    STA third 
    

    ...您失去了 的原始输入third,因此仍然无法产生正确的输出。在您执行的其他地方也会发生同样的情况STA。相反,您可以考虑交换值。通常你需要一个临时变量(一个额外的DAT)。例如,如果您想与 交换secondthird则:

    LDA second
    STA temp
    LDA third
    STA second
    LDA temp
    STA third
    
  • 当您检测到大于复制到时,您首先比较firstand和。奇怪的是,您决定在这一点上参与(对此您没有做出任何结论)。用 . 做一些事情会更有意义。如果您要交换,那么您将得到现在保证不大于的“不变量” ,无论您是从上一条指令分支到该标签还是到达该标签。这是对输入进行排序的第一步。thirdfirstthirdsecondthirdsecondfirst firstthirdfirstthirdbranch1

  • 如果BRP branch3导致跳转到branch3您,最终将只有 2 个输出而不是 3 个。这三个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>

于 2021-10-08T19:42:10.093 回答
1

我建议您为此编写 C 或伪代码。它只会是一两行左右,这将澄清你的想法。

您的伪/C 代码将包含 if-then-else 语句。这是高级 C 中 if-then-else 的模式,然后在低级 C 中重复。当您翻译 if-then-else 语句时,请遵循以下模式:

if ( <condition> ) {
    <then-part>
}
else {
    <else-part>
}

请注意,只有 then-part 和 else-part 之一应该运行。

同样的控制结构,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 中的工作方式:当条件为 false 时,它​​将跳过 then-part 以运行 else-part。但在条件为真时,它不会分支,因此执行 then-part。  在执行 then-part 之后,我们需要跳过 else-partendIf1: ,这就是if-goto-label version 中无条件分支和标签的原因。(如果没有那个无条件分支,它将在 then-part 之后运行 else-part,这会很糟糕。)同样重要的是,在 if-then-else 语句之后,程序运行下一条语句,无论它是否then-part 被解雇或 else-part 被解雇。

如果您有多个 if-then-else 语句,只需为其标签使用不同的编号。嵌套的 if-then-else 仍然应该遵循这种模式——建议先翻译外部的,然后是内部的,但其他顺序也可以。它也可以按程序顺序完成,但这使得遵循这些简单模式变得更加困难。

于 2021-10-08T15:25:06.177 回答