GCSE Von Neumann Architecture (14-16 years)
- An editable PowerPoint lesson presentation
- Editable revision handouts
- A glossary which covers the key terminologies of the module
- Topic mindmaps for visualising the key concepts
- Printable flashcards to help students engage active recall and confidence-based repetition
- A quiz with accompanying answer key to test knowledge and understanding of the module
A-Level Assembly Language (16-18 years)
- An editable PowerPoint lesson presentation
- Editable revision handouts
- A glossary which covers the key terminologies of the module
- Topic mindmaps for visualising the key concepts
- Printable flashcards to help students engage active recall and confidence-based repetition
- A quiz with accompanying answer key to test knowledge and understanding of the module
Assembly Language programming using the Little Man Computer Simulator.
- The LMC instruction set
- A summary table of the LMC instruction set
- Input and Output (INP and OUT)
- Using labels
- Load and save (LDA and STA)
- Add and subtract (ADD and SUB)
- Branching (BRZ, BRA and BRP)
- Decisions (BRP and BRA)
- Replicating an IF/ELSE/ENDIF conditional programming structure
- Replicating a WHILE/ENDWHILE iteration (loop) programming structure
A Little Man Computer (LMC) is a simulator that has many of the basic features of a modern computer that uses the Von Neumann architecture (a central processing unit consisting of an arithmetic logic unit and registers, a control unit containing an instruction register and program counter, input and output mechanisms, and RAM to store both data and instructions).
The LMC is based on the idea of a ‘Little Man’ acting as the control unit of a CPU, fetching instructions from RAM, decoding and executing them as well as managing the input and output mechanisms.
The two versions on this website can be programmed by using a basic set of 10 assembly code instructions which are then assembled into machine code (although in decimal not binary).
Understanding the LMC simulator
- The 100 memory addresses in the computer memory are numbered 0 to 99 and can each contain a ‘machine code‘ instruction or data.
- Each assembly language instruction is made up of a 3 letter mnemonic (which represents the operation code), usually followed by the memory address of the data the CPU is to act on (this is called absolute memory addressing).
- Pressing the Assemble Program button translates the assembly language instructions into ‘machine code‘ and loads them into RAM. it also resets the Program Counter to zero.
- The Input box allows the user to enter numerical data (-999 to 999) while a program is running and load it into the accumulator.
- The Output box can output the contents of the accumulator while a program is running.
- A RAM memory address that is used to store data can be given a meaningful label. Data can also be stored in these named address locations.
- The results of any ADD or SUBTRACT instructions are stored in the accumulator .
- The Program Counter stores the memory address of the instruction being carried out. It will automatically increment by 1 after each instruction is completed.
- If the CPU receives an non-sequential instruction to branch (BRP, BRP or BRZ) then the Program Counter is set to the memory address of that instruction.
- Branch instructions are set to branch to a labelled memory location.
- To restart a program, the Program Counter is reset to 0.
When assembled, each assembly code instruction is converted into a 3 digit ‘machine code’ instruction (1 digit for the instruction and 2 for the memory address). The 3 digit ‘machine code’ instructions are then loaded into RAM, starting at memory address 0.
Any data is also loaded into memory at the memory address corresponding to the location of the data in the program (i.e. if the 5th line of the assembly language program was data then this data would be loaded into address 4, because memory address start at 0 not 1)
The ‘Little Man’ can then begin execution, starting with the instruction in RAM at memory address 0.
The ‘Little Man’ performs the following steps to execute a program:
- Check the Program Counter so it knows the memory address to look at.
- Fetch the instruction from the memory address that matches the program counter.
- Increment the Program Counter (so that it contains the memory address of the next instruction).
- Decode the instruction (includes finding the memory address for any data it refers to).
- If required by the instruction code, fetch the data from the memory address found in the previous step.
- Execute the instruction and if necessary set the Program Counter to match any branch instructions.
Some programming tasks to try using the LMC
- Write a program that will prompt for 2 numbers, subtract the first from the second and output the answer, then subtract the second from the first and output the answer.
- Write a program to output the numbers 1 to 10 in ascending order.
- Write a program to output the numbers 1 to 10 in descending order.
- Write a program to input a number then count up to that number in steps of 2, outputting the sequence.
- Write a program that will input two numbers and multiply them.
- Extend the program above that it will let the user repeatedly input and multiply pairs of numbers, only stopping if a zero is entered.
- Extend the program above so it will let the user enter either or both numbers as negative values.
- Write a program that will prompt for 2 numbers and check if they are the same. If they are then the program should output the number 1. If they are not then the program should output the number 0.
- Write a program that will input an number, then output the square of the number.
- Modify the squares program above so if an input above 31 is entered then it will output a zero.
- Modify the squares program above so it will also square negative number inputs.
- Write a program to input 3 numbers and then output the highest.
- Write a program to input 3 numbers and then output the highest AND the lowest.
- Write a program to divide one number by another.
- Modify the previous program so it generates a decimal answer rather than a remainder.
A simple way to do this is to multiply the remainder by 10 and then divide this number by the original divisor. If this is repeated it will generate the result of the division to unlimited decimal places. This can be done in 42 lines of LMC code. - Write a program to input a number and then outputs:
a) the number
b) the integer square root
c) the remainder.
A simple way to calculate an integer square root is to count how many times increasing odd numbers can be subtracted from the starting value.
32-1=31 -> 31-3=28 -> 28-5=23 -> 23-7=16 -> 16-9=7 -> 7-11<0
1 2 3 4 5 -> SQR(32) = 5 remainder 7
This can be done by ‘dividing’ 355 by 113 to get the integer 3. The remainder is ‘multiplied’ by 10 and then ‘divided’ again by 113 to get the first decimal place. This is then repeated 6 times. 355/113 is used as there is no “better approximation” among all fractions (P/Q) with denominators less than 30,000.
Factors to consider when writing programs in assembly language/machine code using the LMC
- How easy is it to follow programs with many conditional instructions or iteration loops?
- What are the issues when trying to create program structures such as subroutines, for/next loops, while/endwhile loops, repeat/until loops or if/then/else/endif decisions?
- Is the fact that there are only 100 address locations in RAM to store both the program instructions and the data an issue?
- Does it matter that data can normally only be placed in the memory address of the DAT statement?
- Does that fact that instructions and data are both stored together in RAM cause any issues when writing a program?
- Can the equivalent of an array be created to store and process a series of values as a program runs?
- Is it easy to carry out non-integer arithmetic?
- What if you needed higher level functions such as square-roots, trigonometry or needed more complex calculations that would require brackets and the use of AND/OR/NOT?
- What if you wanted to incorporate text or basic graphics in your program?
Demonstration programs using the LMC
Bubble Sort
inputLoop INP
BRZ sortLoop
store DAT 380
LDA store
ADD increment
STA store
LDA listSize
ADD increment
STA listSize
BRA inputLoop
sortLoop LDA listSize
SUB increment
STA loopCount
LDA zero
STA isChange
load1 DAT 580
STA buffA
load2 DAT 581
STA buffB
cmp SUB buffA
BRP nextItem
swap LDA buffB
store1 DAT 380
LDA buffA
store2 DAT 381
LDA increment
STA isChange
nextItem LDA store1
ADD increment
STA store1
ADD increment
STA store2
LDA load1
ADD increment
STA load1
ADD increment
STA load2
LDA loopCount
SUB increment
STA loopCount
BRZ isFinished
BRA load1
isFinished LDA isChange
BRZ outputList
resetLoop LDA lda1
STA load1
ADD increment
STA load2
LDA sta1
STA store1
ADD increment
STA store2
BRA sortLoop
outputList DAT 580
OUT
LDA outputList
ADD increment
STA outputList
LDA listSize
SUB increment
STA listSize
BRZ end
BRA outputList
end HLT
zero DAT 0
buffA DAT 0
buffB DAT 0
isChange DAT 0
increment DAT 1
listSize DAT 0
loopCount DAT 0
sta1 DAT 380
lda1 DAT 580
Trinum
start INP
STA value
LDA zero
STA trinum
STA n
loop LDA trinum
SUB value
BRP endLoop
LDA n
ADD one
STA n
ADD trinum
STA trinum
BRA loop
endLoop LDA value
SUB trinum
BRZ equal
LDA zero
OUT
BRA done
equal LDA n
OUT
done BRA start
value DAT
trinum DAT
n DAT
zero DAT 0
one DAT 1
The triangular numbers are as follows:
1 = 1
3 = 1 + 2
6 = 1 + 2 + 3
10 = 1 + 2 + 3 + 4
15 = 1 + 2 + 3 + 4 + 5
21 = 1 + 2 + 3 + 4 + 5 + 6
etc.
Number Store
writeLoop INP
BRZ readLoop
writeStart DAT 350
LDA writeStart
ADD one
STA writeStart
LDA count
ADD one
STA count
BRA writeLoop
readLoop LDA count
SUB one
STA count
BRZ done
readStart DAT 550
OUT
LDA readStart
ADD one
STA readStart
BRA readLoop
done HLT
count DAT 1
one DAT 1
The program has to alter some instructions as it runs. It does this by treating them as data (they are loaded, altered, and saved) and in this program, the ‘data’ values 350 and 550 are treated as STA (store) and LDA (load) instructions respectively by the LMC. This ‘data’ is altered as the program runs by adding a 1 to it so that it stores INPUT values in memory locations 50 onwards.
Memory Overwrite
BRA writeLoop
s1 DAT
s2 DAT
s3 DAT
s4 DAT
s5 DAT
s6 DAT
s7 DAT
s8 DAT
s9 DAT
writeLoop INP
BRZ readLoop
writeStart DAT 300
LDA writeStart
ADD one
STA writeStart
LDA count
ADD one
STA count
BRA writeLoop
readLoop LDA count
SUB one
STA count
BRZ done
readStart DAT 500
OUT
LDA readStart
ADD one
STA readStart
BRA readLoop
done HLT
count DAT 1
one DAT 1