1

Could someone help me understand, why this work only when input<69 ? I'm working with simple assembly code for 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

I'm use of http://peterhigginson.co.uk/lmc/ to try to work this program

SVLK
  • 11
  • 2
  • what type of a question is this? what domain of programming? – Anantha Raju C Jan 27 '17 at 10:48
  • simpy assemble code for Little Man Computer. this only work when input is less than 69, and I dont know why – SVLK Jan 27 '17 at 11:16
  • Where did you get this code? I believe it's an adaptation of code that I authored, with some very minor adaptations. You can see a link to my original code on my blog: http://paulhankin.github.io/LittleManComputer/ . I personally think my LMC emulator is better than the one you're currently using, but perhaps I'm biased :) – Paul Hankin Jul 05 '17 at 08:12
  • The edits you have made prevent it from working no matter the input. – Paul Hankin Jul 08 '17 at 05:41

1 Answers1

0

The program breaks down above input value 69, because of the limited memory that is available to an LMC. The highest possible address (mailbox) is 99.

This code uses memory space for the sieve, which needs to be as large as the input you give to it. The memory for the sieve starts at mailbox 31, which is defined at label LDINS and STINS in your code: 531 means LDA 31, where 31 is a mailbox address. Similarly 331 means STA 31. This defines the maximum size of the sieve: 31 to 99 gives a total of 69 mailboxes that can serve for the sieve.

The instruction STA WRINS will dynamically change the code at label WRINS so that it writes a value in the sieve array. The dynamic opcode written is 300 + 31 + [some dynamic offset]. The 300 stands for STA, and 31 is where the sieve array starts. Now when the offset is 69 or more, this instruction becomes 400 or more, which no longer represents a STA instruction, but an undefined opcode.

You can run your code in the snippet below, and when you give it 70 as input, you will see it stalls at that instruction saying that the opcode is invalid:

#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>

So concluding, this behaviour is not really a bug in the program, but more a memory limitation of the LMC. An LMC implementation of the Sieve of Eratosthenes will always have a limitation somewhere around that size, depending how concise you can make the code -- leaving room for the array.

Remarks about the code

The above answers your question, but there are some comments to make about your code.

It seems you modified an existing program, adding some preliminary instructions to output 2 and 3 quickly, but you didn't adapt the starting address of the sieve memory in accordance. In your current program the address 31 points to the line (mailbox) with BRA WRITELOOP, which cannot be your purpose. The first time the dynamic code at READINS is executed, that location has instruction LDA INPUT as INPUT, corresponding to address 33.

This is also the reason why the program does not output 5 as a prime. The program should really point to free memory for its sieve, beyond the data you already have in use. To save space you could let the sieve address start at label ONE, since the first two entries of the sieve are never accessed.

I think it is also better to use labels and mnemonics instead of hardcoded opcodes and addresses, so avoiding things like 331 and 531, which are quite cryptic, and (as demonstrated) are error prone when the program is modified.

Also, you should explicitly list the DAT entries that your program will use.

Here is a corrected version, which obviously still has a limit on the input: 67 is the maximum value you can input without breaking the code.

#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>
trincot
  • 317,000
  • 35
  • 244
  • 286