In 2020, I released a new simulator called ARMlite in conjunction with a new A-level textbook on Assembly Language Programming written by Richard Pawson. ARMlite has more memory (1 MB), a cleaner interface, an extended instruction set (interrupts, subroutines, a stack etc.) and is much higher performance (1-10 million instructions per second, depending on your browser and computer). You can get the student version of Richard's book from the ARMlite documentation page or the teachers' version by registering with CAS.

The latest Version of this AQA Simulation is V0.08 - see the end of this document for the new features in V0.07 and V0.08


The object of this simulator is to allow students to gain some familiarity with the Assembly Language specified by AQA for use in the AS and A level computer science papers. The implementation took my previous LMC simulator as a base and anyone familiar with that will hopefully find this easy to use. You can write a program in the Assembly Language area, change the contents of memory or the PC and show memory in signed (default), unsigned, hex or binary. You can add spaces and comments in sensible places.


There is a project for the AQA simulation written by Richard Pawson Write a complete Snake game in AQA Assembly Language.


AQA do not specify their language in enough detail to create an assembler so some assumptions have to be made.

The AQA Instruction Set.

Extension - data

The pseudo-instruction DAT allows you to put a number into a memory cell using the assembler. You can leave out the DAT and just put the number. A label as data will also work.

Extensions - INP and OUT.

These work the same way as on the LMC. INP Rd,2 reads a number into register d and OUT Rd,4 outputs the number from register d. For OUT, device 4 is treated as signed but you can output unsigned (device 5), hex (device 6) or character (device 7). You can input hex as 0xnnn everywhere a number is expected. Like HALT, INP and OUT use the Software Interrupt instruction - this is similar to the way programs call the Operating System or the BIOS to do I/O.

In the 2017 AS paper, AQA use a memory address to control a motor and many modern computers do I/O through addresses rather than special purpose instructions. However on all systems I know of the I/O addresses are not near the memory addresses and the STR R0, 17 (used in the question) could not be assembled using any part of the ARM instruction set. (The correct code is MOV R1,#17; STR R0, [R1] but AQA don't have indirect addressing either.)

Extension - Indirect Addressing.

You can, as people did with the LMC, address a list (or array) by building your own instruction and then executing it. Since AQA do not specify the instruction format you cannot do that with their instructions and neither is there any way to find out what number is associated with a label or memory ref (in the AQA specification). Most modern computers do not allow you to modify your own instructions (or in some the result may be unpredictable). ARM does not have any direct memory instructions - if you look how LDR and STR are encoded, you will find that the addresses are formed by adding or subtracting numbers from the PC (called relative addressing).

So for LDR and STR I have implemented what ARM call "register offset addressing" where you write [Rn+<label>] and the address used is formed by adding the contents of the register to the label. In the default word mode the register is incremented by one to access the next word. In byte mode you need to add 4 (which is the same as ARM).

If you just say [Rn] then the address used is the contents of the register. This is true "indirect addressing" but you have no way in the AQA instruction set of knowing the real memory addresses. In the simulator this can be done.

It is also possible to use [Rn+xxx] where xxx is a positive number and the number of words to add to the register contents (not bytes). Note that the byte/word mode selection affects the use of the register contents during execution but not the interpretation of the offset xxx by the assembler.

Extension - Comments.

Comments are useful so anything after a '/' is taken as a comment. In the examples, I have used '//' to follow the style of many higher level languages.

Self-Modifying Code

Building your own ARM instructions is not easy and with modern computers self-modifying code is regarded as poor practice. However in this simulator and with some instructions there are simple changes you can make. An important thing to remember is that ARM does not have direct addressing and so all the AQA direct instructions are actually implemented as an offset from "PC+8" (i.e. the instruction after the next one).

Just because it is possible does not mean you have to do it. Please use the indirect addressing extension instead.


As some of you may know, I don't agree with MAR and MBR because it is very hard to find anything that exactly implements them in any modern CPU design I have ever seen. However they are in your syllabus so I thought I would give in and put them where they might actually be. For LDR/STR you may notice a slight stutter in some modes while the simulator shows you the instruction fetch in MAR/MBR followed by the values used by the LDR or STR. In all other cases (if you single step) the instruction fetch is the only memory reference.

The MAR always shows the address in denary and the MBR always shows the data in hexadecimal. (I know this is not particularly consistent but a signed MBR would need three more digits and binary one 24 more digits.)


"SELECT" allows you to choose one of a few example programs to assemble and, if you wish, alter and/or run.


There are some options under the "OPTIONS" drop down. "Clr memory" clears memory and the next four ("signed", "unsigned", "hex" and "binary") select the mode to show the contents of memory and the registers. Signed means two's complement signed and hex is short for hexadecimal (base 16 with a=10, b=11, c=12, d=13, e=14 and f =15). Binary only shows the memory in binary. The data blobs normally follow the display mode (except binary which would be too big) but the addressing blobs (red) are normally in denary.

The next four options control the speed of execution. "def normal" is the default speed (7.5) showing the moving data blobs. Once running you can change the speed from 0 (def slow) to 12.5 and still see the moving blobs. "def execute" is the slowest speed (15) to execute without the delay of moving blobs and "def fast" (24) is the fastest the simulator will go and still show all progress on the screen. You can increase the speed up to 24.9 while running at the expense of not refreshing the screen after each instruction.

The next two options control the memory addressing mode (byte/word). The last two control whether the Assembly Language window shows you the line number in the program or the word address in memory.


The Status Register holds the result of the last CMP operation - negative (N), zero (Z), carry (C) and overflow (V). Overflow is for a 2's complement compare whereas Carry means no overflow for the compare seen as an unsigned operation.

The Z flag is tested by the BEQ and BNE instructions. BLT tests (N set and V clear) OR (N clear and V set) and BGT tests Z clear AND (N and V both set or both clear). AQA don't give you instructions to use or test C. (C is important for doing extended and/or unsigned arithmetic - for example 64 bits or more on a 32 bit computer or 32 bits as unsigned.)

In the AQA instruction set, CMP is the only instruction that sets the status bits.

Fetch/Execute Cycle

This is animated by moving blobs. As I expected the size of some of the data blobs with 32 bit numbers is sometimes an issue and there seem to be browsers that do not scale text and graphics at the same rate.

Version V0.07

This was produced in co-operation with who has produced a set of course notes culminating in a snake game which you can play on the simulator. V0.07 has a number of extra features designed to make the operation of the game possible and the programming task slightly simpler. The SELECT option "New I/O" is a example of using the new features.

Version V0.08

I am grateful to Daniel Stone at Reading School for pointing out that with Chrome or Safari on MacOS, the memory and register cells display incorrectly. The root cause of this is that, in those configurations, &numsp; is considerably wider than the space taken up by a number leading to padding pushing numbers beyond the assigned field. (Firefox on MacOS is better but not perfect.)

The best solution I can find (given the way the Simulator is structured) is to use &ensp; for padding. In all the tests I have seen this makes no difference to the displays of any browser on Windows OS (which all display correctly) but does fix Chrome and Safari on MacOS. Firefox on MacOS seems to have &numsp; bigger and &ensp; smaller that the correct number space - so I feel smaller is safer; it is however noticable. There are no other changes between V0.07 and V0.08.

The Simulator

© 2017-8 Peter L Higginson (plh256 at

I am debugging this using Chrome so if you get any problems if would help me if you could check whether they appear in Chrome as well. Please feel free to send me any comments whatsoever.

The LMC simulator is at and the RISC simulator is at

Disclaimer - I am not associated with AQA in any way and this simulator is based on their public documentation.