Explaining the code: the init section
Let’s have a look at the code and see what it does. Here are the first few instructions:
mem[0] = 0x173C
mem[1] = 0x1639
mem[2] = 0x1200
mem[3] = 0x1100
The first instruction 0x173C
is of the form LDI reg, val
with reg
equal to 0x7
and val
equal to 0x3C
. All together this results in LDI 7, 0x3C
. Register 7 is also called the return stack base pointer RB
and 0x3C
is 60 in decimal. This gets us LDI RB, 60
.
Similar considerations for the next three instruction lead to:
LDI RB, 60
LDI DB, 57
LDI RS, 0
LDI SP, 0
All of these instructions are decoded by this piece of code:
elif (n3 == 0x1): # LDI reg, val
self.R[n2] = (n1 << 4) + n0
They initialize the return and the data stacks with base pointer and index each. The memory is prefilled with sentinel values 0xFFFF
and 0x9999
respectively to make debugging easier:
mem[57] = 0xFFFF <--- Start of data stack
mem[58] = 0xFFFF
mem[59] = 0xFFFF
mem[60] = 0x9999 <--- Start of return stack
mem[61] = 0x9999
mem[62] = 0x9999
Of course, the stack would normally be put much higher into memory to leave room for longer programs and you would use labels like DS_START
and RS_START
for referencing the base addresses.