The S16 simulator
Getting to know the simulator
The S16 architecture is a fictional Harvard-architecture stack machine with a 16-bit word and 4KB each of code and data memory, an operation stack which holds up to 256 words and a separate return stack with up to 256 words.
You can interact with it through a browser simulator at
https://www.ole.bris.ac.uk/bbcswebdav/courses/COMSM1302_2020_TB-1/stackmachine/
1
2
3
At the top of the window (1) you have the menu bar – this shows the commands currently available and it changes depending on what you are doing with the program. On the left (2) you have the code window where you can type S16 assembly, and at the bottom (3) a status bar which shows you the current line in the code window as you move the cursor around – this is useful if you get an error message with a line number.
For your first program, you are going to compute 1*2+10. In RPN, this is 1 2 * 10 + and on a stack machine, you use a push instruction to add a constant on the stack and an add/multiply etc. operation removes as many values off the stack as it needs, and puts the result on the stack.
Enter the following code in the code window:
University of Bristol COMSM1302 bristol.ac.uk
PUSH #1
PUSH #2
MUL
PUSH #A
ADD
The hash sign indicates a constant – this particular machine only accepts hexadecimal, so you encode 10 as A.
Next, use the “assemble” menu item – if you did everything right you will see this:
1
2
4
3
You are now in execute mode. The menu bar (1) has changed to reflect this, and the window on the left (2) now shows a disassembly of the code memory. The status bar (3) indicates that assembilng your code was successful. On the right, the view window (4) shows either the stack (currently empty) or the start of the data memory, you can press the links at the top to switch between the two. The command window (5) lets you step and run the simulator and it shows some information like the current program counter, the next instruction and the top of the stack.
First, press “reset” to initialise the processor. Then use the “step” button and watch how the instructions execute one by one and the results appear in the stack window. At the end, the command window should show “Machine state: HALTED” and the stack should contain the single hexadecimal value C (=12).
Reset the processor and press “run” this time, it should step through all instructions and pop up a message when done. In a longer program, you can use the “Faster / Slower” menu items while the processor is running to speed it up (in slow mode, each instruction is artifically delayed to take half a second).
University of Bristol COMSM1302 bristol.ac.uk
5 5
Next, use the “Edit” menu item to go back into edit mode, replace the code with the following and then assemble it again:
PUSH #0
start:
PUSH #1
ADD
J start
The line “start:” is called a label. Labels are a word with a colon at the end, and you can combine them with instructions e.g. you could also write “start: PUSH #1” all on one line. In the last line, J is a jump (branch) instruction, and start is the operand.
Notice how in the disassembly in run mode, the label has disappeared and the branch instruction has now changed to “jump to memory location 2”:
0x0000: 0001 0000 PUSH #0
0x0002: 0001 0001 PUSH #1
0x0004: 0101 ADD
0x0005: 0401 0002 J #2
This means that, starting from code memory location 0, the first two words (0001 0000) represent the “PUSH 0” instruction. Indeed, 0001 is the opcode for PUSH and 0000 is its operand. Next, we have two words 0001 0001: the first is the opcode for PUSH again, the second is the operand 1. Next, 0101 is the opcode for ADD (this takes no argument so it is only a single word long), then 0401 is the opcode for J(ump). The assembler has worked out that the label start referred to the following “PUSH #1” instruction, which begins at memory location 2, so the operand to the jump instruction is 2.
Reset the processor and run the code. You will notice that it implements a loop: starting with a 0 on the stack, each time round it pushes a 1 and then adds it to the previous value, then jumps back to the start of the loop. The result is that you have a loop doing roughly the following:
int i = 0;
while (1) {
i++; }
Or, put another way:
int i = 0;
start:
i++;
goto start;
This is perfectly legal C code, but it is also considered very bad style – quite apart from being an infinite loop. Luckily, the simulator has an “interrupt” menu item while it is running, to stop the program again.
Go back to edit mode and change the program as follows (new line in bold):
University of Bristol COMSM1302 bristol.ac.uk
PUSH #0 start: PUSH #1 ADD INT
J start
INT(errupt), opcode FFFF, is a debugging instruction – when the simulator is running and encounters one of these, it stops, but you can continue if you like by pressing “Run” again. It has the same function as a breakpoint in higher-level code. In fact, some debuggers implement breakpoints with a kind of interrupt instruction internally in real processors.
Run the program a few times now (you might want to switch to fast mode) and you will see that each time through the loop, the value on the stack increases by 1.
University of Bristol COMSM1302 bristol.ac.uk