如何在小人计算机程序中产生股息和余数?

How to produce dividend and remainder in a little man computer program?

我正在尝试编写一个 LMC 程序,它接受两个整数输入,将它们相除,然后产生商和余数。首先,我将问题分为 4 个阶段:

1.Divide num1 除以 num2 得到商,q。

2.Multiply q 和 num2 得到精确的相乘数,存入 num2.

3.Subtract num1 中的 num2,并将答案存储在 rem 中。

4.Output q 和 rem.

这是我写的代码:

    INP 
    STA NUM1
    LDA NUM1
    STA ORG
    INP
    STA NUM2
    BRZ END
    LDA 99
    STA Q
    LOOP   LDA NUM1
    BRZ END
    LDA NUM1
    SUB NUM2
    STA NUM1
    LDA Q
    ADD ONE
    STA Q
    BRA LOOP
    LDA Q
    STA NUM3
    LDA NUM2
    SUB ONE
    STA NUM2
    LOOP    LDA NUM2
    BRZ END
    LDA NUM3
    ADD Q
    STA NUM3
    LDA NUM2
    SUB ONE
    STA NUM2
    BRA LOOP
    LOAD ORG
    SUB NUM3
    STA REM
    END LDA Q
    OUT Q
    LDA REM
    OUT REM
    HLT
    NUM1    DAT
    NUM2    DAT
    ORG     DAT
    Q       DAT
    ONE     DAT 1
    TOTAL   DAT 
    NUM3    DAT
    REM     DAT

当我尝试 运行 LMC 模拟器中的代码时,它没有产生结果,而是无限期地继续计算。我怎样才能让它发挥作用?有一个更好的方法吗?非常感谢任何帮助。

Is there a better way to do this?

您的方法是合乎逻辑的,但可能矫枉过正。单独做除法,当你不能再从被除数中减去除数时停止,将同时产生商和余数。

例如,如果要将 13 除以 4,则 13 减去 4 得到 9,然后 9 减去 4 得到 5,然后 5 减去 4 得到 1,现在我们停止,因为 4 大于1(我们不能不减去负数)。商是我们能够减去 4 的次数(是 3 次),余数是停止后剩下的,这里是 1。


How can I make it work?

至于为什么您的代码会无限循环,可能是因为您只是通过使用 BRZ 来寻找精确的除法。您应该考虑改用 BRP,这将允许非零余数。您应该在 LMC 调试器中单步执行,看看为什么它不会在您希望的时候停止。

你的程序有几个问题:

  • OUT 不接受参数。它不应该是 OUT Q,而只是 OUT。一个好的LMC模拟器应该会抱怨这个。
  • LOOP 被定义为标签两次。这是模棱两可的。一个好的LMC模拟器应该会抱怨这个。
  • BRA LOOP 下方的代码在 END 处的指令之前无法访问。这是死代码。
  • 只有当NUM1 变为零时才能退出循环,但这可能永远不会发生。例如,如果您将 4 除以 5,则减法将产生负溢出,并且累加器将不会为零(实际上它没有由语言定义,然后它会有什么值)。您应该使用 BRP.
  • 构建循环条件逻辑,而不是在那里使用 BRZ
  • Q的初始化取自99号邮箱,但前提是你的程序不占用99号邮箱。这个是对的,不过最好给一个DAT 0打个标签.
  • 没问题,但是不需要第三条指令 (LDA NUM1),因为累加器已经有了那个值。

你要实现的算法有点啰嗦。在您从第一个数字中减去第二个数字并且没有更多的减法是可能的之后,您将已经有了余数(如果您做对了)。

您的算法还应该以不同方式处理 0 除数:在这种情况下,可能会输出一些预定义的值以指示商未定义,例如 999。

这里是你如何编码的。这是一个可运行的片段,其中包含一些您可以改编的示例输入:

#input: 19 5
          LDA zero       # initialise
          STA quotient
          INP
          STA remainder
          INP
          STA divisor
          BRZ error      # division by 0 is undefined
loop      LDA remainder
          SUB divisor
          BRP continue
end       LDA quotient   # output the results
          OUT
          LDA remainder
          OUT
          HLT
continue  STA remainder
          LDA quotient
          ADD one
          STA quotient
          BRA loop
error     LDA big     # output 999 twice to indicate error
          OUT
          OUT
          HLT
remainder DAT
divisor   DAT
quotient  DAT
zero      DAT 0
one       DAT 1
big       DAT 999


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