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
DATinstruction. In the above algorithm we want the counter to start at 10:Then when you need to loop, decrement the counter:
And (like many LMC programs), you need a constant
ONEfor this: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). TheBRPinstruction (branch when positive) will use that flag to decide whether to jump or not:LOOPshould 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:
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:
Then you would do a comparison of the accumulator with POW_9 by:
The label allows us to store a different instruction there, so that the next time it is executed it actually executes this:
This is possible with the following manipulation:
This is a bit tricky because code is treated as data, and this modifies the code. Notice how changing
SUB POW_9is 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
DATlist. For that you could compare the modified code with a fixed piece of code (also aSUB, but which is never executed) that references the lowest power of 2.Here is an implementation of this idea: