1.2.4 - Little Man Computer programs
Little Man Computer makes a program's storage and control decisions visible. You will follow the accumulator, write arithmetic and branch instructions, and check that a small assembly program produces the intended output.
Instructions act on an accumulator and mailboxes
An LMC program exposes individual machine operations and their order.
Assembly language
An assembly language represents a machine's instructions using mnemonics such as LDA and labels for locations. An assembler translates that source into machine code.
Assembly is tied to the instruction set of a particular machine; LMC is a simplified teaching machine, not the instruction set of every processor.
Assembly is useful when software needs precise control of a machine's registers, hardware operations or instruction sequence. The cost is more detail to manage and less portability between architectures than high-level code; mnemonics do not remove that machine dependence.
The LMC model has addressed mailboxes holding instructions or data, an accumulator holding the current arithmetic value, and a program counter identifying the next instruction. Ordinary execution moves to the next instruction; a branch changes that next position. Input places a value in the accumulator. Output copies the accumulator to the output device: it does not automatically output a named mailbox.
| Instruction | Effect |
|---|---|
INP / OUT | Read input into / output the accumulator |
LDA address | Copy the value at that address into the accumulator |
STA address | Copy the accumulator into that mailbox |
ADD address / SUB address | Add / subtract the value stored at that address |
BRA label | Continue at the labelled instruction unconditionally |
BRZ label | Branch when the accumulator is zero |
BRP label | Branch when the subtraction/arithmetic result is nonnegative, including zero |
HLT | Halt execution |
DAT value | Reserve a data mailbox, optionally with an initial value |
A label gives a location a readable name. It is not a new variable that moves between locations: the assembler resolves it to an address. DAT is an assembler directive reserving data, not an instruction to execute. Place data after HLT so ordinary execution does not fall into it.
OCR also accepts STO, LOAD, BR, BZ, BP, IN/INPUT and COB/END for the corresponding instructions. A simulator may choose different aliases. Use the printed meanings, especially BRP's zero case.
Mnemonics make machine instructions readable; they do not make assembly independent of the machine. These LMC examples remain static assembly, not runnable Python.
Store values before another input replaces them
The accumulator holds only one current value, so a second input replaces the first unless you store it. This program inputs two nonnegative integers whose sum is at most 999 and outputs their sum.
INP
STA FIRST
INP
ADD FIRST
OUT
HLT
FIRST DAT 0
For inputs 18 then 7, follow the effect of each instruction rather than guessing from the labels.
| After instruction | Accumulator | FIRST | Output |
|---|---|---|---|
| INP | 18 | 0 | none |
| STA FIRST | 18 | 18 | none |
| INP | 7 | 18 | none |
| ADD FIRST | 25 | 18 | none |
| OUT | 25 | 18 | 25 |
ADD FIRST adds the contents of FIRST, not its address. This is direct addressing. LDA FIRST would replace the accumulator with 18; it would not add 18. A comment or a label does not change either operation.
LMC simulators normally have three-digit mailboxes. Overflow and the display of negative subtraction results vary between implementations. Our arithmetic examples avoid overflow; when a comparison is needed, we reason about the subtraction's zero/nonnegative condition rather than output a negative result.
Subtract to decide which branch to take
A comparison can be implemented by subtraction followed by a conditional branch. If the first number minus the second is zero, they are equal; if it is nonnegative, the first is at least as large. Subtraction changes the accumulator, so reload an original value when you need to output it.
This original program inputs two numbers in 0–999 and outputs the smaller, including when they are equal.
INP
STA FIRST
INP
STA SECOND
LDA FIRST
SUB SECOND
BRP SECONDOUT
LDA FIRST
BRA DISPLAY
SECONDOUT LDA SECOND
DISPLAY OUT
HLT
FIRST DAT 0
SECOND DAT 0
With 4 then 9, the comparison has a negative result, so BRP is not taken and FIRST is loaded. With 9 then 4, BRP is taken and SECOND is loaded. With 4 then 4, the zero condition also takes BRP, correctly outputting 4. The unconditional BRA DISPLAY prevents the FIRST route from falling through into LDA SECOND.
Use BRZ when equality alone matters. For example, after LDA COUNT and SUB LIMIT, BRZ DONE takes the branch only when COUNT and LIMIT are equal. BRP DONE would also take it when COUNT exceeds LIMIT.
A loop needs a changing value and a stopping branch
A branch back to an earlier label creates repetition, but it terminates only if the tested state can reach the stopping condition. This program accepts a count in 0–999, outputs that many descending positive integers, and outputs nothing for zero.
INP
STA COUNT
LOOP LDA COUNT
BRZ DONE
OUT
SUB ONE
STA COUNT
BRA LOOP
DONE HLT
COUNT DAT 0
ONE DAT 1
For input 3, COUNT is tested at 3, 2, 1 and 0. The output sequence is 3, 2, 1. Subtracting ONE changes the accumulator; STA COUNT saves that decrease for the next iteration. Omitting STA would cause the next LDA to reload the unchanged count and repeat forever for a positive input.
The zero check occurs before output. If moved after OUT, input zero would output zero once, violating the contract. For input 1, the loop outputs 1, stores 0, then halts on its next visit to LOOP. The precondition excludes negative inputs and does not promise behavior for them.
Write and amend code from its input and output contract
To design a short LMC routine, decide which values must survive the next input or arithmetic operation, then allocate DAT locations. Put branches around genuinely different routes; identify the join and the halt before writing the body. Finally trace normal and boundary inputs against the required output.
For a program that inputs a number in 0–499 and outputs double it, store the input as VALUE, then add VALUE to the still-current accumulator. A complete solution is:
INP
STA VALUE
ADD VALUE
OUT
HLT
VALUE DAT 0
The 499 bound matters: the largest requested result is 998, within a three-digit mailbox. Tests 8→16, 0→0 and 499→998 check ordinary, minimum and maximum cases. Replacing ADD with LDA would output the original number; adding an extra INP would wrongly require a second input. Alternative designs can load/add a stored input more than once if they satisfy the same contract.
These are static assembly examples. As ungraded practical writing, use a local editor or compatible LMC simulator to write a three-input sum program, then test 10, 0, 7→17 and 300, 300, 300→900. Preserve the partial sum before the third input replaces the accumulator. Enter the labelled source, assemble it, inspect its address listing and single-step while watching the accumulator, data mailboxes and program counter. Confirm the simulator's supported aliases, three-digit range and negative-result/overflow behavior before interpreting a trace. NovaLearn Testing uses static LMC interpretation, diagnosis and design reasoning here; its Python runner and source editors do not assess LMC assembly.