- Stack of size 1000 elements each 4 bytes.
- A boolean bit.
- A program counter.
# Hello world program
__CODE__ # start code segment
# PUSH the string Hello World! in reverse order.
# 0 indicates end of string.
PUSH &end # the return address.
PUSH 0
PUSH 10 # new line.
PUSH '!'
PUSH 'D'
PUSH 'L'
PUSH 'R'
PUSH 'O'
PUSH 'W'
PUSH 32 # space
PUSH 'O'
PUSH 'L'
PUSH 'L'
PUSH 'E'
PUSH 'H'
PUSH Ah # new line. (in hexadecimal).
PUSH &print # call print function.
GOTO
:end
END
########## PRINT SUBROUTINE ###########
:print
PUSH 0
EQU
POP # pop the 0.
PUSH &ret # If top of stack is zero stop printing.
GOIF
WRTC # print the character.
PUSH &print # loop.
GOTO
:ret
POP # POP the 0.
GOTO # TOS is return address, so go to it.
:end
REAH - read a hexadecimal byte from stdin
to top of stack
READ - read a decimal to top of stack.
REAC - read a character to top of stack.
WRTH - write a hexadecimal byte to stdout.
WRTD - write a decimal to stdout.
WRTC - write a character to stdout.
ADD - add top 2 elems of stack and put sum
in stack
SUB - subtract topmost element by 2nd
topmost element from stack and put
difference in top of stack
MUL - multiply top 2 elems os stack and
put product in top of stack
DIV - Divide topmost elem by 2nd topmost
elem and put quotient in top of
stack and remainder below top.
POP - pop topmost elem from stack
EQU - if top 2 elems are equal boolean
flag set to 1 else 0
GRT - is top is greater than second top
boolean flag set to 1 else 0
LST - is top is smaller than second top
boolean flag set to 1 else 0
GOTO - go to instruction number given by
top of stack.
GOIF - like GOTO but only if boolean flag
set.
GOUN - like GOTO but only if boolean flag
not set.
END - end execution.
DUP - Duplicate the topmost element on
the stack.
FLIP - Flip the top two elements on the
stack.
GET - Push the element at data segment
address given by the top of stack.
PUT - Put the second in top of stack to
the location given by top of stack.
NOP - No operation.
PUSH - push a byte to top of stack. Byte may
be entered as a decimal or a hexadecimal
with a suffix 'h'.
LAB - Defines a label at this point.
IND - Indirection, defines that next 4 bytes
is an address.
In a second pass of compilation LAB is replaced by NOP and IND is compiled to PUSH .
A label can be defined with the ':' character, and can be jumped to with GOTO, GOIF or GOUN instructions, for example-
....code....
:start \# Definition of a label.
....code....
GOTO &start \# Jump to label
To push data from data segment to stack, first push the address to the stack then use GET, for example-
:my_data 123
__CODE__
PUSH &my_data
GET
Similarly, PUT can be used to write data from the stack to the data segment.
Use the # character for comments.
First compile file to byte code.
./compiler hw.vm
Then run the compiled .vmc file in the vm.
./vm hw.vmc
To decompile the code to a .vm file use decompiler.
./decompiler hw.vmc