Eratosthenes筛子小人计算机

时间:2017-01-27 10:43:01

标签: sieve-of-eratosthenes little-man-computer

有人可以帮助我理解,为什么只有在输入< 69时才能工作?   我正在使用Little Man Computer的简单汇编代码

    INP 
    STA INPUT
    LDA C
    OUT 
    ADD ONE
    OUT
LOOP LDA A  \\ first loop
    ADD ONE
    STA A
    SUB INPUT
    BRP END
    LDA A
    ADD LDINS
    STA READINS
READINS DAT
    BRZ PRIME
    BRA LOOP
PRIME LDA A
    OUT
    STA B
WRITELOOP LDA B  \\ second loop
    SUB INPUT
    BRP LOOP
    LDA B  \\ at this moment program breakdown when input is more than 69
    ADD STINS
    STA WRINS
    LDA A 
WRINS   DAT
    LDA B
    ADD A
    STA B
    BRA WRITELOOP
END     HLT
INPUT   DAT 0
LDINS   DAT 531  \\ this is working, but i think i might do a better code 
STINS   DAT 331
A       DAT 1
ONE     DAT 1
B       DAT
C       DAT 2

我使用http://peterhigginson.co.uk/lmc/来尝试使用此程序

1 个答案:

答案 0 :(得分:0)

由于LMC可用的内存有限,程序在输入值69以上崩溃。最高可能的地址(邮箱)是99。

此代码使用筛子的存储空间,该空间需要与您为其输入的输入一样大。筛子的内存始于邮箱31,邮箱31在代码中的标签LDINSSTINS上定义:531表示LDA 31,其中31是邮箱地址。类似地331表示STA 31。这定义了筛子的最大尺寸:31到99个筛子总共可以容纳69个邮箱。

指令STA WRINS将动态更改标签WRINS上的代码,以便将其值写入sieve数组。写入的动态操作码为300 + 31 + [某些动态偏移量]。 300代表STA,而31是筛分阵列的起始位置。现在,当偏移量为69或更大时,此指令将变为400或更大,不再代表STA指令,而是未定义的操作码。

您可以在下面的代码段中运行您的代码,当将其输入70时,您将看到该代码停滞在该指令上,表明操作码无效:

#input: 70
    INP 
    STA INPUT
    LDA C
    OUT 
    ADD ONE
    OUT
LOOP LDA A  \\ first loop
    ADD ONE
    STA A
    SUB INPUT
    BRP END
    LDA A
    ADD LDINS
    STA READINS
READINS DAT
    BRZ PRIME
    BRA LOOP
PRIME LDA A
    OUT
    STA B
WRITELOOP LDA B  \\ second loop
    SUB INPUT
    BRP LOOP
    LDA B  \\ at this moment program breakdown when input is more than 69
    ADD STINS
    STA WRINS
    LDA A 
WRINS   DAT
    LDA B
    ADD A
    STA B
    BRA WRITELOOP
END     HLT
INPUT   DAT 0
LDINS   DAT 531  \\ this is working, but i think i might do a better code 
STINS   DAT 331
A       DAT 1
ONE     DAT 1
B       DAT
C       DAT 2
 
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc@v0.76/lmc.js"></script>

因此,结论是,此行为实际上不是程序中的错误,而是LMC的内存限制。 LMC的Eratosthenes筛网的实现始终会在该大小附近有所限制,具体取决于您可以使代码简明扼要-为数组留出空间。

关于代码的注释

以上内容回答了您的问题,但是对于您的代码有一些注释。

似乎您修改了一个现有程序,添加了一些初步指令以快速输出2和3,但是您没有按照相应的要求调整筛网存储器的起始地址。在当前程序中,地址31指向带有BRA WRITELOOP的行(邮箱),这不是您的目的。第一次执行READINS处的动态代码时,该位置的指令LDA INPUTINPUT,对应于地址33。

这也是程序不输出5作为质数的原因。该程序实际上应该指出其可用内存的余量,而不是已经使用的数据。为了节省空间,您可以让筛子地址以标签ONE开头,因为从未访问过筛子的前两个条目。

我认为使用标签和助记符代替硬编码的操作码和地址也更好,因此避免使用诸如331和531之类的含糊不清的东西(如所示),并且在修改程序时容易出错。 >

此外,您应该明确列出程序将使用的DAT条目。

这里是更正后的版本,显然仍然对输入有限制:67是您输入的最大值而不会破坏代码。

#input: 67
          INP 
          STA INPUT
LOOP      LDA A    \\ first loop
          ADD ONE
          STA A
          SUB INPUT
          BRP END
          LDA A
          ADD LDINS
          STA READINS
READINS   DAT
          BRZ PRIME
          BRA LOOP
PRIME     LDA A
          OUT
          STA B
WRITELOOP LDA B     \\ second loop
          SUB INPUT
          BRP LOOP
          LDA B
          ADD STINS
          STA WRINS
          LDA A 
WRINS     DAT
          LDA B
          ADD A
          STA B
          BRA WRITELOOP
END       HLT
INPUT     DAT
LDINS     LDA ONE
STINS     STA ONE
A         DAT 1
ONE       DAT 1    // also the start of the sieve
B         DAT

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