A cheatsheet for Hack's virtual machine language


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 //

Valid Names

A valid name must begin with a letter or underscore. The remaining characters can be digits, letters, or underscores



Operates on most recent stack value


neg Negate


not Not

For example:

push constant 6
neg              // yields -6


Operates on the two most recent stack values


add Add

sub Subtract

mul Multiply*

div Divide*


eq Equal to

ne Not equal to

lt Less than

gt Greater than

lte Less than or equal

gte Greater than or equal


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 )


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


Memory segment

Holds arbitrary temporary variables


Memory segment

Holds the static variables of the classes used by the running program


Pseudo memory segment in stack

Holds the local (var type) variables declared by the current subroutine


Pseudo memory segment in stack

Holds the arguments passed to the current subroutine



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



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)
	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


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
D = M;   // top of stack = Memory[ THIS ]

// -- Set value of THIS pointer to most recent stack value --

// pop pointer 0
M = D;   // Memory[ THIS ] = top of stack


Pseudo memory segment. It is not allocated space in memory

Used to push positive integers onto the stack

Stack Actions

Move data into and out of the stack


push segmentName index

Copy the value in the specified location (segmentName index), and place it in the stack


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 Actions

Jump to a location in the program code


goto labelName

Jumps immediately to labelName


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 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



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


1The save and restore code is generated by the VM compiler


Specific locations in the program


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


		push argument 0
		push constant 0
		if-goto WHILE_BODY    // if n > 0, goto WHILE_BODY
		goto WHILE_END        // else, goto WHILE_END


		push argument 0
		push constant 1
		pop argument 0        // n = n - 1

	label WHILE_END

		push constant 33      // '!'
		call GFX.printChar 1
		pop temp 0

	push constant 0           // return 0


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 ]

//	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
	pop  local    0           // s = x - x2

	push local    0           // return s

See valid names