How to loop and encode as binary? - little-man-computer

I am trying to get a program running in the LMC that converts any numerical to binary.
Normally I would just use the divide method, but I cannot do that since the Little Man Computer does not allow for divide or multiplication. The farthest I've gotten in this is only a simple INP. At this stage I do not know how to start loops in it, or how to even begin.
How can I start loops? And how do I stop them? I would somehow need a repeating loop that subtracts a value until it either reaches a 1 or 0. That will achieve my goal as I can just output it then.
For example: I enter 33 and it gives a 100 001 in the output.
I'm a total beginner. I just picked it up today, so keeping it simple would be greatly appreciated.

You write that for 33 the output should be 100 001. This may not work (depending on the LMC simulator), as the second value could be output without the prepadded zeroes, and so it would show 100 1. This can be confusing as it looks a lot like what you would expect for input 9.
I would suggest outputting each binary digit as a separate number: that way you ensure that all digits are visible in the output.
An algorithm to encode an input n like that, could be as follows:
Compare n with 512. If it is not less:
a. Output 1, and subtract 512 from n, otherwise:
b. Output 0
Double the value of n, i.e. add n to itself
Repeat the above 9 more times. Decrement a counter that starts with 10 and repeat as long as it does not set the negative flag.
How to loop
So you "start" a loop in a static way: set the initial value of a counter in a DAT instruction. In the above algorithm we want the counter to start at 10:
COUNTER DAT 10
Then when you need to loop, decrement the counter:
LDA COUNTER
SUB ONE
STA COUNTER
And (like many LMC programs), you need a constant ONE for this:
ONE DAT 1
Finally, to know whether the counter did not go below 0, you can check the "negative" flag. This is a flag that can be set by SUB, when there is a negative overflow (remember that the LMC cannot really store negative values, so you only have the flag as indication). The BRP instruction (branch when positive) will use that flag to decide whether to jump or not:
BRP LOOP
LOOP should be the label for where the code of your loop started.
Implementation
Note that in this practical case, it isn't useful to execute this loop more than 10 times, since the input in LMC cannot be more than 999, which in binary takes 10 digits.
Here is the implementation of the above described algorithm, with also a precaution that the counter will start at its initial value even when the program counter is reset after a first execution:
#input:13
INP
STA NUM
LDA NINE
LOOP STA COUNTER
LDA NUM
COMPARE SUB POW_9
BRP BIT1
BIT0 LDA ZERO
OUT
BRA DOUBLE
BIT1 STA NUM ; Reduce number with 512
LDA ONE
OUT
DOUBLE LDA NUM
ADD NUM
STA NUM
LDA COUNTER
SUB ONE
BRP LOOP
ZERO HLT
POW_9 DAT 512
ONE DAT 1
NINE DAT 9
NUM DAT
COUNTER DAT
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc#v0.7/lmc.js"></script>
Alternative
There are several other ways to accomplish this task. For instance, we can hard-code the powers of 2 that we need for 10 binary digits: 1, 2, 4, ..., 512.
Then compare the input value with the greatest of those (with 29 = 512). If it is not less, then output a 1 bit, otherwise output 0. If 1, then subtract that power of 2 from the input number. In both cases, switch to the previous power of 2 (28) and repeat this process. Repeat this until you've done the job for 20.
You could try to implement this without a loop, but you'll have 10 times the same code, with just a different power of 2. This may even be a challenge to fit in the LMC's memory of 100 "mailboxes" (It would work however if you limited the input to like 64, so you would only need 6 binary digits).
To implement this with a loop (less code), you can use a technique of indirect addressing. In LMC there is no instruction for indirect addressing, but with self-modifying code it is possible.
Suppose you have the list of powers implemented as follows:
POW_9 DAT 512
POW_8 DAT 256
; ... etc
POW_0 DAT 1
Then you would do a comparison of the accumulator with POW_9 by:
COMPARE SUB POW_9
The label allows us to store a different instruction there, so that the next time it is executed it actually executes this:
COMPARE SUB POW_8
This is possible with the following manipulation:
LDA COMPARE
ADD ONE
STA COMPARE
This is a bit tricky because code is treated as data, and this modifies the code. Notice how changing SUB POW_9 is actually working as if you reference an element in an array, and increase the index in that array.
You need to have a stop-condition so that you don't make the code reference a power of 2 that is not in your DAT list. For that you could compare the modified code with a fixed piece of code (also a SUB, but which is never executed) that references the lowest power of 2.
Here is an implementation of this idea:
#input:13
INP
STA NUM
LDA FIRST
LOOP STA COMPARE ; self-modifying code!
SUB LAST ; Compare with "SUB ZERO"
BRP ZERO
LDA NUM
COMPARE SUB POW_9 ; Indirect addressing
BRP BIT1
BIT0 LDA ZERO
OUT
BRA NEXT
BIT1 STA NUM ; Reduce number with power
LDA ONE
OUT
NEXT LDA COMPARE ; Change power of 2
ADD ONE
BRA LOOP
FIRST SUB POW_9 ; Never executed
LAST SUB ZERO ; Never executed
POW_9 DAT 512
POW_8 DAT 256
POW_7 DAT 128
POW_6 DAT 64
POW_5 DAT 32
POW_4 DAT 16
POW_3 DAT 8
POW_2 DAT 4
POW_1 DAT 2
ONE DAT 1
ZERO HLT
NUM DAT
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc#v0.7/lmc.js"></script>

Related

How to check if a number is odd or even in little man computer

I need help with making my program produce the correct output.
I am currently working with this code:
INP
STA NUMBER
SUB DIVISOR
BRP VERIFY
BRA CHECK
LOOP STA NUMBER
LDA RESULT
ADD ONE
STA RESULT
VERIFY LDA NUMBER
SUB DIVISOR
BRP LOOP
LDA RESULT
ODD LDA ONE
STA RESULT
EVEN LDA 60
STA RESULT
CHECK LDA RESULT
BRP ODD
BRZ EVEN
OUT
HLT
NUMBER DAT
DIVISOR DAT 2
ONE DAT 1
RESULT DAT 0
When I run the code above on little man computer simulator, it just loops and loops and prints no output. What I wanted to do is divide the inputted number into two and check if it has a remainder. If it has a remainder, then it is an odd number, else it is an even number. I know that the code has errors but I can't pinpoint where the problem lies, maybe you can help me with it. Thanks in advance!
The infinite loop occurs at BRP ODD. Be aware that BRP also branches when the accumulator is zero. So it is a "branch when not negative" instruction. And when the execution continues at ODD, it falls through to EVEN, which makes the code at ODD irrelevant. At EVEN the accumulator is loaded with zero, and so the BRP will branch again... infinitely.
There is also a missing check for 0: when the input is zero, you should not perform the subtraction at all.
Not a problem, but having a reference to mailbox 60 can be better replaced with a reference to a label, like ZERO.
The code includes logic that really isn't necessary:
You have included code to calculate the quotient, since the code adds ONE to the RESULT every time you subtract the DIVISOR from the NUMBER. However, that RESULT is finally overwritten with either ONE or zero (address 60), so that quotient was calculated for nothing. As you only want to output whether the input was odd or even, you should drop the quotient calculation from your code.
Also avoid code repetition. You currently perform the SUB at two different places. This should not be necessary as the logic should be the same in both instances.
Here is the code reduced to its basics:
#input: 11
INP
STA NUMBER
LOOP BRZ OUTPUT # remainder is zero! so output a zero
SUB DIVISOR
BRP LOOP
LDA ONE # when result is negative, input was odd
OUTPUT OUT
HLT
NUMBER DAT
DIVISOR DAT 2
ONE DAT 1
ZERO DAT 0
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc#v0.816/lmc.js"></script>
You can run the simulator in this snippet and then use the buttons to step through the code.

Convert n-bit binary to base 10 number

I am looking at this Little man computer problem:
Write a Little Monkey Computer program that can convert an n-bit binary number into a number using the base-10 number system. Display the natural number as output before halting the program.
The first input determines the value for n. It is assumed this value will be equal to four, or greater.
For example, if the first input is eight (8) then eight subsequent inputs are requested. If the subsequent inputs number were 1, 0, 0, 1, 0, 0, 0, 0 then the output would be 9.
n input values are provided by the user, one for each bit: The first of these is the least-significant bit.
The nth input is the most-significant bit.
My attempt:
IN
STO NUMBER
IN
STO A
IN
STO B
IN
STO C
IN
STO D
LOOPB: LDA FOUR
BRZ ENDB
SUB ONE
STO FOUR
LDA RESB
ADD B
STO RESB
BRP LOOP
ENDB:LDA RESB
OUT
HLT
ONE: DAT 1
EIGHT: DAT 8
FOUR: DAT 4
TWO: DAT 2
POWERONE: DAT 1
RESA: DAT 000
RESB: DAT 000
RESULT: DAT 000
NUMBER: DAT 0
A: DAT 0
B: DAT 0
C: DAT 0
D: DAT 0
I do not how to solve this question, how to make 00001001 would convert to 9 on LMC? I not sure how to do multiplication on LMC.
The code you have does not use the first input. Instead it uses FOUR. This is the first thing to change, as you don't want to loop exactly four times, but as many times as your first input is.
Secondly, you don't need to store each next input in a separate mailbox. Instead you can immediately process the 0/1 input as it decides whether you want to add something to the result or not. So you only need to update the result depending on the input's 0/1 value. You don't need to store that 0/1 value itself -- so no need of A, B, C...etc. Instead put the IN instruction inside the loop.
Then remains what exactly you should add to the result when an input turns out to be 1. As the input is in reversed order (the least significant bits come first), you should keep track of a power of 2, which you double in each iteration of the loop. That will be the number to add to the result whenever you encounter an input of 1. Because that is how the binary system works. For instance if the input of digits is 1 1 0 1, then the calculation is:
input digit
power of 2
to be added
running sum
1
1
yes
1
1
2
yes
3
0
4
no
3
1
8
yes
11
So here is the script for that. You can run it here: first run the code snippet (which starts the LMC simulator) and then use the controls in the right panel:
#input:8 1 0 1 1 0 0 0 0
LDA ZERO # Initialise, so program still runs
STO RESULT # correctly when it is reset.
LDA ONE
STO POWER
IN # Get number of binary digits
LOOP BRZ OUTPUT # All digits have been read
STO COUNT
IN # Get a binary digit
BRZ NEXT # Nothing to add when it's zero
LDA RESULT # Add a power of 2 to the result
ADD POWER
STO RESULT
NEXT LDA POWER # Next power of 2
ADD POWER
STO POWER
LDA COUNT # Prepare for next iteration
SUB ONE
BR LOOP
OUTPUT LDA RESULT
OUT
ZERO HLT
ONE DAT 1
POWER DAT 1
COUNT DAT
RESULT DAT
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc#v0.816/lmc.js"></script>

How to find the sum of odd numbers in LMC

I am learning LMC, but I am not able to find the sum of odd numbers till 100 in LMC
such as 1+3+5+7... and so on
I did write the code to add the two numbers
INP //here I wil input 1
STA 99
INP // here I will input 2
ADD 99
OUT
HLT
I am not sure how to loop through it, so I can get sum of odd numbers. If someone could please help me?
If you need to output the odd numbers between 1 and 100, then there is no reason to ask the user for input: you have all elements for solving the problem already, so no need to ask anything.
With LMC you often need to define some constant data, like ... the number 1. And for this exercise, the number 2 would also be handy to have prepared. So reserve two "mailboxes" for these two numbers (use DAT).
Here is how the program could iterate over the odd numbers between 1 and 99:
LOOP LDA CURRENT // start with one
OUT // output less than 100
ADD TWO
STA CURRENT
SUB HUNDRED // compare with 100
BRP EXIT // halt when above
BRA LOOP // and repeat
EXIT HLT
CURRENT DAT 1
TWO DAT 2
HUNDRED DAT 100
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc#v0.7/lmc.js"></script>
However, to calculate the sum of those numbers would exceed the capabilities of the LMC. The sum of 1+3+5+..+99 is 2500, while the LMC can only deal with numbers up to 999, so that is not going to work.

LMC Program (Using branch) to store values in different locations

So this is for a school project: I need to design a program (using a branch loop) that stores 1 in memory location 91, 2 in 92 etc... to 5 is stored in 95. I am not very knowledgable of LMC and would like some advice on it. I use peterhigginson.co.uk/LMC for my code (if that helps). The program cannot be as simple as store 1 in 91, it has to be done using a finite loop. I can easily ace this in any other coding console, just not LMC. Any help mucho appreciated.
Thanks!
It's not such an easy question. For code that writes to different addresses, you have to construct the correct STA instructions, using the encoding that STA xx is 3xx.
Here's one way of doing it:
L LDA COUNT
ADD INS
STA X
LDA COUNT
X HLT
LDA COUNT
ADD ONE
STA COUNT
LDA FIVE
SUB COUNT
BRP L
HLT
COUNT DAT 1
ONE DAT 1
FIVE DAT 5
INS STA 90
There's a counter (stored in COUNT) that goes from 1 to 5, and each time through the loop L, it's added to 390 (which is stored at INS) -- this constructs the instructions STA 91, STA 92, .., STA 95 on iterations 1, 2, 3, 4, 5. This instruction is written at X, and then executed with A having the value of COUNT. The rest is just incrementing COUNT, and stopping when it gets larger than 5.
Here's a live link, which you can see this code running on my own LMC emulator.

How do I code the Fibonacci sequence LMC?

I was wondering if it was possible to create a program that creates the Fibonacci Sequence in "Little Man Computer".
The program would output in the letter boxes the individual numbers of the sequence. The only input made would be asking the user how high it would like the sequence to go. For example if I input "20" it would only go up to to number 13.
Any help would be greatly appreciated,
Isaac.
Source: link
INP
STA N
LOOP LDA A
SUB N
BRP ENDLOOP
LDA A
OUT
LDA B
ADD A
STA ACC
LDA B
STA A
LDA ACC
STA B
BRA LOOP
ENDLOOP HLT
A DAT 0
B DAT 1
N DAT
ACC DAT
The fibonacci series can be printed in the LMC in the following manner:
INP
STO n #number of terms
LDA one
OUT
loop LDA fib #THE MAIN LOOP THAT PRINTS FIBONACCI NUMBERS
STO temp2
ADD temp
STO fib
LDA temp2
STO temp
BR check
check LDA n #LOOP TO KEEP A TRACK OF NUMBER OF TERMS
BRZ halt
SUB one
STO n
BRZ halt
LDA fib
OUT
BR loop
halt HLT
n DAT 000
fib DAT 001
temp DAT 001
temp2 DAT 000
one DAT 001
Explanation: The program first asks for an input n, the number of terms to be printed.Then the loop starts running - it will print the default value of variable fib, which has been set to 1. The value of fib is stored in another variable temp2, and the variable temp is used to record the previous value of fib so that the numbers are added correctly and a correct sequence is obtained. The loop controls the values of fib, temp and temp2 as the number of terms are increased.
The program then checks if the number of terms required have been printed and decrements the value of n. If n=0 it means that the required number of terms has been reached and the program halts. If n is not zero, the loop continues till n=0.
**Though there might me more efficient methods, however this one works correctly and uses a pretty less number of mailboxes which makes it quite efficient.