This cheatsheet assumes that you are using this compiler. However, most of the information is also applicable to compilers that follow the specifications of TECS
Use the navigation bar to jump to a section of interest
Case sensitive
File extension is .vm
Single line comments start with //
A valid name must begin with a letter or underscore. The remaining characters can be digits, letters, or underscores
Unary
Operates on most recent stack value
Arithemtic
neg
Negate
Bitwise
not
Not
For example:
push constant 6
neg // yields -6
Binary
Operates on the two most recent stack values
Arithemtic
add
Add
sub
Subtract
mul
Multiply*
div
Divide*
Comparison
eq
Equal to
ne
Not equal to
lt
Less than
gt
Greater than
lte
Less than or equal
gte
Greater than or equal
Bitwise
and
And
or
Or
xor
Xor*
lsl
Logical shift left*
lsr
Logical shift right*
For example:
push constant 5
push constant 3
sub // yields 2
push constant 3
neg // yields -3
push constant 2
gte // yields false ( is -3 gte 2, false )
Notes
The mul
, div
, xor
, lsl
, and lsr
operations assume that the Hack computer's ALU can perform them. Though not present in the official TECS architecture, I am in the process of adding them to my version of the ALU
A look at Hack's memory layout diagram might be helpful
temp
Memory segment
Holds arbitrary temporary variables
static
Memory segment
Holds the static
variables of the classes used by the running program
local
Pseudo memory segment in stack
Holds the local (var
type) variables declared by the current subroutine
arg
Pseudo memory segment in stack
Holds the arguments passed to the current subroutine
this
Pointer
Set to point to the base address of the current class instance
Used to access the instance's field variables. For example this 0
points to field 0
For example:
// method void setZ ( int zNew ) {
//
// z = zNew;
// }
method Point.setZ 2 // two arguments: pointer to instance, zNew
push argument 0
pop pointer 0 // Memory[ THIS ] = argument 0 (pointer to instance)
push argument 1 // zNew
pop this 2 // z = zNew
// Memory[ Memory[ THIS ] + 2 ] = zNew
// In this example, Point class has 3 field variables (x, y, z)
push constant 0 // return 0
return
that
Pointer
Typically used to access the contents of an array
This is accomplished by setting that
to the array's base address + desired index
For example:
// function void foo ( Array a, int b, int c ) {
//
// a[ b ] = c;
// }
function className.foo 0
push argument 1 // b
push argument 0 // a (base address)
add
pop pointer 1 // Memory[ THAT ] = a + b
push argument 2 // c
pop that 0 // Memory[ Memory[ THAT ] + 0 ] = c
// Memory[ a + b ] = c
push constant 0 // return 0
return
pointer
Pseudo memory segment. It is not allocated space in memory
Used to access the values of the THIS and THAT pointers:
pointer 0
accesses the THIS pointer
pointer 1
accesses the THAT pointer
Generates assembly code equivalent to:
// -- Retrieve value of THIS pointer and place it in stack --
// push pointer 0
@THIS
D = M; // top of stack = Memory[ THIS ]
// -- Set value of THIS pointer to most recent stack value --
// pop pointer 0
@THIS
M = D; // Memory[ THIS ] = top of stack
constant
Pseudo memory segment. It is not allocated space in memory
Used to push positive integers onto the stack
Move data into and out of the stack
push
push segmentName index
Copy the value in the specified location (segmentName index), and place it in the stack
pop
pop segmentName index
Remove the most recent value from the stack, and place it in the specified location (segmentName index)
See "segments"
Where index is an integer in the range 0 to 32767 (inclusive)
Jump to a location in the program code
goto
goto labelName
Jumps immediately to labelName
if-goto
if-goto labelName
If some condition is true, jumps immediately to labelName
Assumes that the result (True
or False
) of evaluating the condition is the most recent value on the stack
For example:
push argument 0
push constant 78
gt // result of gt comparison is placed on stack
if-goto SOMEWHERE // program counter jumps to SOMEWHERE if the result is true
call
call subroutineName numberOfArguments
Assumes that the arguments intended for the subroutine have already been pushed to the stack
First saves the caller's return address and state (values for the LCL, ARG, THIS, and THAT pointers)1
Then jumps to subroutineName
return
return
Returns to the current subroutine's caller
First restores the caller's state (values for the LCL, ARG, THIS, and THAT pointers)1
Then jumps to the saved return address
Note:
1The save and restore code is generated by the VM compiler
Specific locations in the program
label
label labelName
Marks a point in the program
Used in conjunction with goto labelName
and if-goto labelName
For example:
// function void countdown ( int n ) {
//
// while ( n > 0 ) {
//
// n -= 1;
// }
//
// GFX.printChar( '!' );
// }
function Point.countdown 0
label WHILE_COND
push argument 0
push constant 0
gt
if-goto WHILE_BODY // if n > 0, goto WHILE_BODY
goto WHILE_END // else, goto WHILE_END
label WHILE_BODY
push argument 0
push constant 1
sub
pop argument 0 // n = n - 1
goto WHILE_COND
label WHILE_END
push constant 33 // '!'
call GFX.printChar 1
pop temp 0
push constant 0 // return 0
return
function
function subroutineName numberOfLocalVariables
Block of code
Expects zero or more arguments, uses zero or more local variables, and returns a value
First sets the THIS pointer to:
The value returned by a call to DataMemory.alloc( numberOfFieldVariables ) if the subroutine is a constructor
argument 0 if the subroutine is a method
For example:
// constructor Point new ( int ax, int ay ) {
//
// x = ax;
// y = ay;
//
// return this;
// }
function Point.new 0
push constant 2 // In this example, Point class has 2 field variables (x, y)
call DataMemory.alloc 1 // DataMemory.alloc( 2 )
pop pointer 0 // Memory[ THIS ] = DataMemory.alloc( 2 )
push argument 0 // ax
pop this 0 // x = ax
push argument 1 // ay
pop this 1 // y = ay
push pointer 0 // return Memory[ THIS ]
return
// method int subt ( int x2 ) {
//
// var int s;
//
// s = x - x2;
//
// return s;
// }
function Point.subt 2 // two arguments: pointer to instance, x2
push argument 0
pop pointer 0 // Memory[ THIS ] = argument 0
push this 0 // x
push argument 1 // x2
sub
pop local 0 // s = x - x2
push local 0 // return s
return
See valid names