This is a simulator to demonstrate how processors execute assembler instructions.
The processor is not an actually existing one, but it has the (nice) features from
all kinds of processors.
All data is supposed to be of the same size (16 or 32 bits integer or even floating point(!),
whatever you like).
The instructions aren't really coded in binary and all take one memory location.
Every instruction has at most two arguments and data flows from the right to the left argument.
All numbers are shown decimally (not hexadecimally) just because JavaScript
(in which this program is written) handles that format much more easily,
but you can enter hexadecimal data as 0x45 for example.
The following instructions are currently recognized:
arithmetic:
add,
div,
mod,
mul,
sub
boolean:
and,
eor,
or,
xor
compare:
eq,
ge,
gt,
le,
lt,
ne
move:
mov,
pop,
push
program flow:
halt,
jmp,
jpf,
jpt,
ret
shift:
shl,
shr
The processor handles the compares like a RISC processor
so 'ge r[0],r[1]' means: r[0] becomes r[0]>=r[1].
and it's then usually followed by a jpf (jump if false) or jpt (jump if true)
based on the value of the register with the result (r[0] in this case).
This way no flag register is required, which makes designing the pipe-line
of a RISC computer much easier.
Press on the example buttons to have example code filled in...
Some more notes:
The call/return mechanism works like in a RISC processor
which means that the return address is not being pushed on the stack,
but is saved in a register (in this case called 'ret').
The return from subroutine instruction just moves the return value
back to the ip (instruction pointer) register.
In fact the 'ret' pseudo instruction is translated by the assembler into 'mov ip,ret'.
If the subroutine is going to call one or more other subroutines, the return value can
be saved in the same way as the other registers are being saved by the compiler.
In a lot of RISC processors all registers can be used to store the return address in.
But that would complicate things unnessarily in this simulator.
Of course the push and pop instructions wouldn't be present in a real RISC processor
since they need complicated and therefore time consuming pre-decrement and post increment
operations.
In a RISC processor the stack pointer (sp) is decreased at the start of a subroutine,
to provide enough space for saving registers (including the call return address),
creating local variables, temporary calculation fields and arguments to subroutines.
All this data is then accessed via the sp. This way a frame pointer (fp) isn't even needed.
Most RISC processors have 32 registers and as much as possible data is kept in them
during the life of each function.