【问题标题】:Input three numbers into the LMC and output them largest to smallest?将三个数字输入 LMC 并从大到小输出?
【发布时间】:2021-10-08 14:43:57
【问题描述】:

所以,我已经设法解决了大部分问题,但是如果输入值是递增的,我只能从最大到最小输出吗?第一个 = 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

【问题讨论】:

  • 您收到了一些答案。请留下一些反馈,如果满意,您可以将一个答案标记为已接受。

标签: assembly little-man-computer


【解决方案1】:

一些问题:

  • 当你这样做时:

    LDA second
    STA third 
    

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

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

  • 如果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>

【讨论】:

    【解决方案2】:

    我建议您为此编写 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-part,这就是 if-goto-label 版本中无条件分支和 endIf1: 标签的原因。 (如果没有那个无条件分支,它将在 then-part 之后运行 else-part,这会很糟糕。)同样重要的是,在 if-then-else 语句之后,程序会运行下一条语句,无论它是否then-part 触发或 else-part 触发。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-18
      相关资源
      最近更新 更多