A cheatsheet for Hack's assembly language




About

This cheatsheet assumes that you are using this compiler. However, much 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



Preamble

If you are writing assembly code from scratch, you are free to write or read to any memory location. The only caveat is the section allocated for IO use. Although the assembly code can write here, values written will be reflected in an output device or overwritten by an input device

If you are tweaking assembly code generated by a compiler (VM or HL), you should keep in mind the memory layout that the code assumes



General

Case sensitive

File extension is .asm



Comments

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



Registers

D

Used to facilitate computations

M

Pseudo register (no hardware equivalent)

Used to read from and write to data memory

A

Multiple uses:

As the address when reading from or writing to data memory

As the target address (program position) of a jump

To load a specific integer into another register



Statements

@integer

Sets the value of the A register to the given integer

The integer must be in the range 0 to 32767 (inclusive)

@symbolName

Sets the value of the A register to the address referenced by symbolName

See symbols

destination = computation

The ALU computes the specified computation. Its output is placed in the specified register (destination)

See destination

See computation

computation; jump

The ALU computes the specified computation. Its output is used to determine whether to jump

See computation

See jump



Symbols

Used to give meaningful aliases to locations in memory

Labels refer to locations in program memory (i.e. locations in the executing program)

Variables refer to locations in data memory


Labels

Declaration, ( labelName )

To use, @labelName

Name must be unique. See valid names


Variables

To use, @variableName

Predefined:

address
variableName(s)
0
R0, SP
1
R1, LCL
2
R2, ARG
3
R3, THIS
4
R4, THAT
5
R5
6
R6
...
...
15
R15
SCREEN
KBD
MOUSE

*Address varies depending on color bit mode. See memory layout

Custom variables:

Declaration, @variableName

Name must be unique. See valid names

Mapping starts at address 16. For example, the first variable you declare will refer to dataMemory[16], the second to dataMemory[17] etc.



Destination

Sets the destination register(s) for the ALU's output

Types:

NULL No destination

register[register][register] One or more registers (ex. D, DM, DMA)



Jump

Jumps to a location in the program

More specifically, sets the program counter value to the value of the A register

If conditional, compares the ALU output to zero to determine whether to jump

Types:

NULL Don't jump

JMP Jump (unconditional)

JGT Jump if greater than

JEQ Jump if equal to

JLT Jump if less than

JGE Jump if greater than or equal to

JLE Jump if less than or equal to

JNE Jump if not equal to



Computation

Computations that the ALU can perform


Constant

0 Zero

1 One

- 1 Negative one


Unary

register

! register Not

- register Negate


Binary

register + 1 Add one

register - 1 Subtract one

register op register

+ Add

- Subtract

* Multiply1

/ Divide1

& And

| Or

^ Xor1

<< Logical shift left1

>> Logical shift right1

Note: The registers should be different (ex. D + D is not supported)


Notes

See registers

1The *, /, ^, <<, and >> 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



Examples

Addition:


@35         // A_register holds 35
D = A       // D_register holds 35
@100        // A_register holds 100
D = D + A   // D_register holds 135

Memory access:


// Read contents of Memory[ 999 ] into the D_register
@999
D = M

// Read contents of Memory[ 65534 ] into the D_register
@2
A = - A     // A_register holds -2 (which is equivalent to 65534 in two's complement)
D = M

Array access:


// Let c represent an 'array' that begins at Memory[ 9000 ]
@9000
D = A
@c
M = D       // Memory[ @c ] = 9000

// Set c[ 21 ] = - 1
@c
D = M       // get the array's base address (9000)
@21         // A_register holds index (21)
A = D + A   // A_register holds 9021 (9000 + 21)
M = - 1     // set value;  Memory[ 9021 ] = - 1

Loops:


// --- Computes Memory[ 1 ] = 1 + 2 + ... + Memory[ 0 ]
// --- Usage: load a value into Memory[ 0 ]

// Setup
@i
M = 1		    // Memory[ @i ] = Memory[ 16 ] = 1  // represents i

@sum
M = 0		    // Memory[ @sum ] = Memory[ 17 ] = 0  // represents sum

// Main
(loop)

	// break condition
	@i
	D = M
	@0
	D = D - M   // i - Memory[ 0 ]
	@loopEnd
	D ; JGT		// if i > Memory[ 0 ], exit loop


	// body
	@i
	D = M
	@sum
	M = D + M 	// sum += i

	@i
	M = M + 1 	// i += 1

	@loop
	0 ; JMP 	// go to next iteration of loop

(loopEnd)

	@sum
	D = M
	@1
	M = D 		// Memory[ 1 ] = sum  // done

// Program end
(end)

	@end
	0 ; JMP 	// loop indefinitely