LMC 程序不输出正确的总和

问题描述

loop    inp
        sta numa
        sub validate
endthis brp loop
        bra label1
label1  lda numa
        sub validate1
        brp label2
        brz label2
endthis bra loop
label2  lda num
loop    sta num
        add total
        sta total
        sta num
        sub one
        brp loop
        lda total
        out
validate dat 11
validate1 dat 5
numa    dat
num     dat
total   dat 
one     dat 1

该程序将让用户输入 5 到 10 之间的数字,并计算从 1 到用户指定的输入的数字之和,并将结果打印在输出显示中。例如,如果用户输入 5,则总和为 15。

解决方法

代码存在以下问题:

  • 有些标签不是唯一的,例如 loop。所以这意味着不清楚执行应该用 brp loop 指令跳转到哪里。根据您使用的模拟器,您可以获得不同的行为。您应该为标签使用唯一的名称。

  • 代码的第二部分——计算完成的地方——开始于:

    label2  lda num
    loop    sta num
    

    ...但这只是读取和写入 num 中的内容,这是无用的。您确实想将输入复制到num,因此应该是:

    label2  lda num2
    loop    sta num
    
  • 再往下一点,你有这样的代码:

    sta total
    sta num
    sub one
    

    ...但这会用总数覆盖 num,然后从总数中减去一。但是,您希望从输入数字的倒计时值中减去 1,而不是从总数中减去。所以你真正需要的是获取那个倒计时值然后减去:

    sta total
    lda num    # corrected
    sub one
    
  • 您的程序没有 hlt 指令,这意味着执行将落入程序的“数据部分”。所以在此处添加 hlt

    lda total
    out
    hlt    # stop execution
    

还有以下几点需要改进:

  • 从不引用 endthis 标签:不需要。

  • 在这段代码中:

    brp label2
    brz label2
    

    ... brz 指令永远不会导致跳转到 label2,因为零已经被 brp 捕获。这可能会令人困惑,但 brp 的意思是:“非负时分支”,因此当累加器为零时它也会分支。因此,您可以删除该 brz label2;不需要。

  • 以下 bra 指令:

            bra label1
    label1  lda numa
    

    ... 将跳转到 label1 或者也只是继续该行。所以这是一个无用的跳跃。你可以去掉那 bra label1 行,也去掉标签。

  • LMC 可以重置为从顶部再次运行。在这种情况下,您必须考虑到数据不会重置,因此在程序开始时使用将数据初始化为初始值的代码是一种很好的做法。在这种特殊情况下,您需要将总数重新设置为 0,否则您将添加到之前运行的总数中。

  • 我建议使用更有意义的名称。例如,label1numa 并没有真正阐明它们的用途。

建议的解决方案:

          lda zero   # added: initialise total
          sta total
getinput  inp
          sta input
          sub toogreat
          brp getinput
          lda input
          sub minimum
          brp inputok
          bra getinput
inputok   lda input     # corrected
loop      sta countdown
          add total
          sta total
          lda countdown # corrected
          sub one
          brp loop
          lda total
          out
          hlt   # added
toogreat  dat 11
minimum   dat 5
input     dat 4
countdown dat
total     dat 0 
zero      dat 0
one       dat 1

<script src="https://cdn.jsdelivr.net/gh/trincot/lmc@v0.816/lmc.js"></script>