Little Man Computer Guide: Assembly Programming Basics
Understanding the Little Man Computer
Developed in 1965 by Professor Stuart Madnik, the Little Man Computer (LMC) remains an essential educational tool for understanding computer architecture. This simplified model visualizes a computer as a "little man" processing instructions in a mailroom-like environment. Peter Higgson's popular simulator at University College London makes these concepts tangible by demonstrating how CPUs execute assembly language through its limited instruction set. Unlike high-level languages like Python, LMC requires explicit data movement commands, teaching core programming principles through constraint-based problem solving.
Why LMC Matters Today
Despite its simplicity, LMC effectively demonstrates the von Neumann architecture still used in modern computers. Advanced computer science courses continue to include LMC programming because it:
- Reveals how CPUs interact with RAM
- Teaches fundamental programming logic
- Demonstrates instruction execution cycles
- Provides hands-on assembly experience
The LMC's 11-instruction set forces programmers to build complex operations from basic commands. For example, multiplication requires repeated addition since no dedicated multiply operation exists. This constraint highlights how all programming ultimately reduces to fundamental processor operations.
Core LMC Architecture and Instruction Set
The LMC simulator consists of three key components:
- CPU with accumulator, program counter, and instruction register
- RAM with 100 memory locations (mailboxes)
- I/O for user input and output
The Essential Instruction Set
Each LMC operation has a numeric code that gets converted to binary during assembly:
| Mnemonic | Code | Function |
|---|---|---|
| INP | 901 | Input to accumulator |
| OUT | 902 | Output accumulator |
| STA | 3xx | Store accumulator to address xx |
| LDA | 5xx | Load from address xx to accumulator |
| ADD | 1xx | Add value at xx to accumulator |
| SUB | 2xx | Subtract value at xx from accumulator |
| BRZ | 7xx | Branch to xx if accumulator is zero |
| BRP | 8xx | Branch to xx if accumulator positive |
| BRA | 6xx | Unconditional branch to xx |
| HLT | 000 | Halt program |
| DAT | - | Data declaration |
Critical limitation: LMC uses only direct addressing. You cannot directly use values like ADD 3 - you must store the value 3 in memory first using DAT and reference its location.
The Accumulator's Central Role
The accumulator is the CPU's temporary working memory. Every operation interacts with it:
INPplaces values directly into the accumulator- Arithmetic operations modify the accumulator's contents
OUTdisplays the accumulator's current valueSTAcopies the accumulator to RAMLDAoverwrites the accumulator with RAM contents
Understanding data flow through the accumulator is essential for writing efficient LMC programs. Well-optimized code minimizes unnecessary memory operations by leveraging the accumulator strategically.
Practical LMC Programming Examples
Let's implement the video's programming challenges. These demonstrate core concepts while building problem-solving skills.
Adding Two Numbers
INP // Input first number to accumulator
STA NUM1 // Store to NUM1 (address 09)
INP // Input second number to accumulator
ADD NUM1 // Add NUM1 to accumulator
OUT // Output result
HLT // Stop
NUM1 DAT // Data storage at address 09
Optimized version using one variable:
INP // First number to accumulator
STA TEMP // Store temporarily
INP // Second number to accumulator
ADD TEMP // Add first number
OUT // Output sum
HLT
TEMP DAT
Adding Five Numbers
LDA TOTAL // Load current total
ADD NEXT // Add next number
STA TOTAL // Store updated total
...
TOTAL DAT 0
NEXT DAT
Key insight: Reuse the same memory location for sequential inputs rather than declaring five separate variables. After each INP, immediately add to the running total.
Adding Three and Subtracting Two
... // Code adds first three numbers to TOTAL
INP // Fourth number
STA SUB1 // Store for subtraction
INP // Fifth number
STA SUB2
LDA TOTAL
SUB SUB1 // Subtract fourth
SUB SUB2 // Subtract fifth
OUT
HLT
SUB1 DAT
SUB2 DAT
Pro tip: Use descriptive labels like SUB1 instead of generic names. This improves readability in complex programs.
Adding Three and Doubling
... // Code adds three numbers to TOTAL
LDA TOTAL
ADD TOTAL // Double by self-addition
OUT
HLT
Why this works: Adding a value to itself is equivalent to multiplication by 2, avoiding the lack of a multiply instruction.
Debugging and Simulation Tips
- Step execution: Use the simulator's step function to observe the fetch-execute cycle
- Watch the accumulator: Its value changes after every instruction
- Verify memory: Check if variables contain expected values after stores
- Common errors:
- Forgetting
DATdeclarations - Attempting immediate addressing (
ADD 3instead ofADD THREE) - Not resetting the program counter between runs
- Forgetting
Essential practice: After writing any program, step through it while tracking:
- Current instruction
- Accumulator value
- Relevant memory locations
- Program counter address
Next Steps in LMC Mastery
Having mastered these fundamentals, you're ready for advanced concepts:
- Branching: Implement loops with
BRAand conditional logic withBRZ/BRP - Subroutines: Create reusable code sections
- Algorithms: Develop sorting routines or mathematical functions
- Optimization: Reduce instruction count and memory usage
Actionable Learning Checklist
- Write and test the addition program
- Implement the five-number addition challenge
- Create the add-three-subtract-two program
- Modify a program to use fewer variables
- Step through each program observing register changes
Recommended resources:
- Peter Higgson's LMC Simulator (web-based)
- "The Elements of Computing Systems" textbook
- ARM Assembly Basics (next-step after LMC)
- Structured Programming with LMC (research paper)
Which LMC concept have you found most challenging to implement? Share your experience in the comments below.