CSCE-312 Day 1 Introduction
L16 – Writing Basic HACK Programs
Hack assembly language (overview)
Semantics:
Computes the value of comp
Stores the result in dest
If the Boolean expression (comp jump 0) is true,
jumps to execute the instruction at ROM[A]
where:
0, 1, -1, D, A, !D, !A, -D, -A, D+1, A+1, D-1, A-1, D+A, D-A, A-D, D&A, D|A
M, !M, -M, M+1, M-1, D+M, D-M, M-D, D&M, D|M
comp =
null, JGT, JEQ, JGE, JLT, JNE, JLE, JMP
jump =
null, M, D, MD, A, AM, AD, AMD
dest =
(M refers to RAM[A])
dest = comp ; jump
(both dest and jump are optional)
C-instruction:
A-instruction:
where value is either a constant or a symbol referring to such a constant
@value // A = value
credit: nand2tetris.org
2
Hack assembler
Assembly program
// Program: Flip.asm
// flips the values of
// RAM[0] and RAM[1]
@R1
D=M
@temp
M=D // temp = R1
@R0
D=M
@R1
M=D // R1 = R0
@temp
D=M
@R0
M=D // R0 = temp
(END)
@END
0;JMP
Hack
assembler
Binary code
0000000000000001
1111110000010000
0000000000010000
1110001100001000
0000000000000000
1111110000010000
0000000000000001
1110001100001000
0000000000010000
1111110000010000
0000000000000000
1110001100001000
0000000000001100
1110101010000111
load &
execute
We’ll develop a Hack assembler later in the course.
credit: nand2tetris.org
3
Symbolic program implemented as a text file
3
CPU Emulator
A software tool
Convenient for debugging and executing symbolic Hack programs.
load
CPU Emulator
Assembly program
// Program: Flip.asm
// flips the values of
// RAM[0] and RAM[1]
@R1
D=M
@temp
M=D // temp = R1
@R0
D=M
@R1
M=D // R1 = R0
@temp
D=M
@R0
M=D // R0 = temp
(END)
@END
0;JMP
(the simulator software translates from symbolic to binary as it loads)
credit: nand2tetris.org
4
Symbolic program implemented as a text file
4
Registers and memory
RAM
ROM
instructions
data out
data in
CPU
M register
D register
A register
D: data register
A: address / data register
M: the currently selected memory register: M = RAM[A]
credit: nand2tetris.org
5
Registers and memory
Typical operations:
D: data register
A: address / data register
M: the currently selected memory register: M = RAM[A]
credit: nand2tetris.org
6
Registers and memory
// D=10
@10
D=A
// D++
D=D+1
// D=RAM[17]
@17
D=M
// RAM[17]=D
@17
M=D
Typical operations:
D: data register
A: address / data register
M: the currently selected memory register: M = RAM[A]
credit: nand2tetris.org
7
Registers and memory
// RAM[17]=10
@10
D=A
@17
M=D
// RAM[5] = RAM[3]
@3
D=M
@5
M=D
// D=10
@10
D=A
// D++
D=D+1
// D=RAM[17]
@17
D=M
// RAM[17]=D
@17
M=D
Typical operations:
D: data register
A: address / data register
M: the currently selected memory register: M = RAM[A]
credit: nand2tetris.org
8
Program example: add two numbers
Hack assembly code
credit: nand2tetris.org
9
Program example: add two numbers
// Program: Add2.asm
// Computes: RAM[2] = RAM[0] + RAM[1]
// Usage: put values in RAM[0], RAM[1]
@0
D=M // D = RAM[0]
@1
D=D+M // D = D + RAM[1]
@2
M=D // RAM[2] = D
Hack assembly code
4
5
0
1
2
3
32767
@0
D=M
0
1
Memory (ROM)
@1
D=D+M
2
3
@2
M=D
4
5
6
7
8
9
10
11
12
13
14
15
(white space
ignored)
translate and load
symbolic view
credit: nand2tetris.org
10
32767
Program example: add two numbers
0000000000000000
1111110000010000
0
1
Memory (ROM)
0000000000000001
1111000010010000
2
3
0000000000000010
1110001100001000
4
5
6
7
8
9
10
11
12
13
14
15
// Program: Add2.asm
// Computes: RAM[2] = RAM[0] + RAM[1]
// Usage: put values in RAM[0], RAM[1]
@0
D=M // D = RAM[0]
@1
D=D+M // D = D + RAM[1]
@2
M=D // RAM[2] = D
Hack assembly code
4
5
0
1
2
3
binary
view
translate and load
credit: nand2tetris.org
11
Terminating a program
@0
D=M
0
1
Memory (ROM)
@1
D=D+M
2
3
@2
M=D
4
5
6
7
8
9
10
11
12
13
14
15
4
5
0
1
2
3
// Program: Add2.asm
// Computes: RAM[2] = RAM[0] + RAM[1]
// Usage: put values in RAM[0], RAM[1]
@0
D=M // D = RAM[0]
@1
D=D+M // D = D + RAM[1]
@2
M=D // RAM[2] = D
Hack assembly code
credit: nand2tetris.org
12
Terminating a program
@0
D=M
0
1
Memory (ROM)
@1
D=D+M
2
3
@2
M=D
4
5
6
7
8
9
10
11
12
13
malicious code
starts here…
14
15
4
5
0
1
2
3
// Program: Add2.asm
// Computes: RAM[2] = RAM[0] + RAM[1]
// Usage: put values in RAM[0], RAM[1]
@0
D=M // D = RAM[0]
@1
D=D+M // D = D + RAM[1]
@2
M=D // RAM[2] = D
Hack assembly code
Resulting from some attack on the computer
credit: nand2tetris.org
13
Terminating a program
@0
D=M
0
1
Memory (ROM)
@1
D=D+M
2
3
@2
M=D
4
5
6
7
8
9
10
11
12
13
14
15
4
5
0
1
2
3
// Program: Add2.asm
// Computes: RAM[2] = RAM[0] + RAM[1]
// Usage: put values in RAM[0], RAM[1]
@0
D=M // D = RAM[0]
@1
D=D+M // D = D + RAM[1]
@2
M=D // RAM[2] = D
Hack assembly code
credit: nand2tetris.org
14
Terminating a program
// Program: Add2.asm
// Computes: RAM[2] = RAM[0] + RAM[1]
// Usage: put values in RAM[0], RAM[1]
@0
D=M // D = RAM[0]
@1
D=D+M // D = D + RAM[1]
@2
M=D // RAM[2] = D
@6
0;JMP
Hack assembly code
Best practice:
To terminate a program safely, end it with an infinite loop.
4
5
6
7
0
1
2
3
@0
D=M
Memory (ROM)
@1
D=D+M
@2
M=D
@6
0;JMP
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Jump to instruction number A
(which happens to be 6)
0: syntax convention for jmp instructions
credit: nand2tetris.org
15
Built-in symbols
symbol value
R0 0
R1 1
R2 2
… …
R15 15
The Hack assembly language features built-in symbols:
These symbols can be used to denote “virtual registers”
Example: suppose we wish to use RAM[5] to represent some variable,
say x, and we wish to let x=7
// let RAM[5] = 7
@7
D=A
@5
M=D
implementation:
Attention: Hack is case-sensitive! R5 and r5 are different symbols.
better style:
// let RAM[5] = 7
@7
D=A
@R5
M=D
credit: nand2tetris.org
16
16
Built-in symbols
symbol value
R0 0
R1 1
R2 2
… …
R15 15
The Hack assembly language features built-in symbols:
credit: nand2tetris.org
17
17
Built-in symbols
symbol value
R0 0
R1 1
R2 2
… …
R15 15
SCREEN 16384
KBD 24576
The Hack assembly language features built-in symbols:
symbol value
SP 0
LCL 1
ARG 2
THIS 3
THAT 4
R0, R1 ,…, R15 : “virtual registers”, can be used as variables
SCREEN and KBD : base addresses of I/O memory maps
Remaining symbols: used in the implementation of the Hack virtual
machine, discussed in chapters 7-8.
credit: nand2tetris.org
18
18
OUTLINE
Hack programming
Part 1: registers and memory
Part 2: branching, variables, iteration
Part 3: pointers, input/output
Project 4 overview
19
Branching
credit: nand2tetris.org
20
Branching
// Program: Signum.asm
// Computes: if R0>0
// R1=1
// else
// R1=0
example:
credit: nand2tetris.org
21
Branching
// Program: Signum.asm
// Computes: if R0>0
// R1=1
// else
// R1=0
// Usage: put a value in RAM[0],
// run and inspect RAM[1].
example:
credit: nand2tetris.org
22
Branching
// Program: Signum.asm
// Computes: if R0>0
// R1=1
// else
// R1=0
// Usage: put a value in RAM[0],
// run and inspect RAM[1].
@R0
D=M // D = RAM[0]
@8
D;JGT // If R0>0 goto 8
@R1
M=0 // RAM[1]=0
@10
0;JMP // goto end
@R1
M=1 // R1=1
@10
0;JMP
8
9
10
11
4
5
6
7
0
1
2
3
example:
credit: nand2tetris.org
23
Branching
// Program: Signum.asm
// Computes: if R0>0
// R1=1
// else
// R1=0
// Usage: put a value in RAM[0],
// run and inspect RAM[1].
@R0
D=M // D = RAM[0]
@8
D;JGT // If R0>0 goto 8
@R1
M=0 // RAM[1]=0
@10
0;JMP // goto end
@R1
M=1 // R1=1
@10
0;JMP
8
9
10
11
4
5
6
7
0
1
2
3
example:
credit: nand2tetris.org
24
Branching
“Instead of imagining that our main task as programmers is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.”
– Donald Knuth
// Program: Signum.asm
// Computes: if R0>0
// R1=1
// else
// R1=0
// Usage: put a value in RAM[0],
// run and inspect RAM[1].
@R0
D=M // D = RAM[0]
@8
D;JGT // If R0>0 goto 8
@R1
M=0 // RAM[1]=0
@10
0;JMP // goto end
@R1
M=1 // R1=1
@10
0;JMP
8
9
10
11
4
5
6
7
0
1
2
3
cryptic code
example:
credit: nand2tetris.org
25
Branching
// Program: Signum.asm
// Computes: if R0>0
// R1=1
// else
// R1=0
// Usage: put a value in RAM[0],
// run and inspect RAM[1].
@R0
D=M // D = RAM[0]
@POSITIVE
D;JGT // If R0>0 goto 8
@R1
M=0 // RAM[1]=0
@10
0;JMP // goto end
(POSITIVE)
@R1
M=1 // R1=1
(END)
@END
0;JMP
example:
8
9
10
11
4
5
6
7
0
1
2
3
referring to a label
declaringa label
credit: nand2tetris.org
26
Labels
Label resolution rules:
Label declarations
generate no code
Each reference to a
label is replaced with
a reference to the instruction number following that label’s declaration.
32767
@0
D=M
0
1
Memory
@8 // @POSITIVE
D;JGT
2
3
@1
M=0
4
5
@10 // @END
0;JMP
6
7
@1
M=1
8
9
@10 // @END
0;JMP
10
11
12
13
14
15
resolving
labels
// Program: Signum.asm
// Computes: if R0>0
// R1=1
// else
// R1=0
// Usage: put a value in RAM[0],
// run and inspect RAM[1].
@R0
D=M // D = RAM[0]
@POSITIVE
D;JGT // If R0>0 goto 8
@R1
M=0 // RAM[1]=0
@10
0;JMP // goto end
(POSITIVE)
@R1
M=1 // R1=1
(END)
@END
0;JMP
example:
8
9
10
11
4
5
6
7
0
1
2
3
referring to a label
declaringa label
credit: nand2tetris.org
27
Labels
Implications:
32767
@0
D=M
0
1
@8 // @POSITIVE
D;JGT
2
3
@1
M=0
4
5
@10 // @END
0;JMP
6
7
@1
M=1
8
9
@10 // @END
0;JMP
10
11
12
13
14
15
// Program: Signum.asm
// Computes: if R0>0
// R1=1
// else
// R1=0
// Usage: put a value in RAM[0],
// run and inspect RAM[1].
@R0
D=M // D = RAM[0]
@POSITIVE
D;JGT // If R0>0 goto 8
@R1
M=0 // RAM[1]=0
@10
0;JMP // goto end
(POSITIVE)
@R1
M=1 // R1=1
(END)
@END
0;JMP
example:
8
9
10
11
4
5
6
7
0
1
2
3
resolving
labels
Memory
referring to a label
declaringa label
credit: nand2tetris.org
28
Labels
Implications:
Instruction numbers no longer needed in symbolic programming
The symbolic code becomes relocatable.
32767
@0
D=M
0
1
@8 // @POSITIVE
D;JGT
2
3
@1
M=0
4
5
@10 // @END
0;JMP
6
7
@1
M=1
8
9
@10 // @END
0;JMP
10
11
12
13
14
15
// Program: Signum.asm
// Computes: if R0>0
// R1=1
// else
// R1=0
// Usage: put a value in RAM[0],
// run and inspect RAM[1].
@R0
D=M // D = RAM[0]
@POSITIVE
D;JGT // If R0>0 goto 8
@R1
M=0 // RAM[1]=0
@10
0;JMP // goto end
(POSITIVE)
@R1
M=1 // R1=1
(END)
@END
0;JMP
example:
8
9
10
11
4
5
6
7
0
1
2
3
resolving
labels
Memory
referring to a label
declaringa label
credit: nand2tetris.org
29
Variables
// Program: Flip.asm
// flips the values of
// RAM[0] and RAM[1]
Variable usage example:
credit: nand2tetris.org
30
Variables
// Program: Flip.asm
// flips the values of
// RAM[0] and RAM[1]
// temp = R1
// R1 = R0
// R0 = temp
@R1
D=M
@temp
M=D // temp = R1
@R0
D=M
@R1
M=D // R1 = R0
@temp
D=M
@R0
M=D // R0 = temp
(END)
@END
0;JMP
Variable usage example:
credit: nand2tetris.org
31
Variables
Variable usage example:
// Program: Flip.asm
// flips the values of
// RAM[0] and RAM[1]
// temp = R1
// R1 = R0
// R0 = temp
@R1
D=M
@temp
M=D // temp = R1
@R0
D=M
@R1
M=D // R1 = R0
@temp
D=M
@R0
M=D // R0 = temp
(END)
@END
0;JMP
symbol
used for the first time
symbol used again
credit: nand2tetris.org
32
Variables
Variable usage example:
32767
@1
D=M
0
1
Memory
@16 // @temp
M=D
2
3
@0
D=M
4
5
@1
M=D
6
7
@16 // @temp
D=M
8
9
@0
M=D
10
11
@12
0;JMP
12
13
14
15
resolving
symbols
Symbol resolution rules:
A reference to a symbol that has no corresponding label declaration is treated
as a reference to a variable
If the reference @ symbol occurs in the program for first time, symbol is allocated to address 16 onward (say n), and the generated code is @ n
All subsequencet
@ symbol commands are translated into @ n
// Program: Flip.asm
// flips the values of
// RAM[0] and RAM[1]
// temp = R1
// R1 = R0
// R0 = temp
@R1
D=M
@temp
M=D // temp = R1
@R0
D=M
@R1
M=D // R1 = R0
@temp
D=M
@R0
M=D // R0 = temp
(END)
@END
0;JMP
In other words: variables are allocated to RAM[16] onward.
symbol
used for the first time
symbol used again
credit: nand2tetris.org
33
Variables
Variable usage example:
Implications:
// Program: Flip.asm
// flips the values of
// RAM[0] and RAM[1]
// temp = R1
// R1 = R0
// R0 = temp
@R1
D=M
@temp
M=D // temp = R1
@R0
D=M
@R1
M=D // R1 = R0
@temp
D=M
@R0
M=D // R0 = temp
(END)
@END
0;JMP
symbolic code is easy
to read and debug
32767
@1
D=M
0
1
Memory
@16 // @temp
M=D
2
3
@0
D=M
4
5
@1
M=D
6
7
@16 // @temp
D=M
8
9
@0
M=D
10
11
@12
0;JMP
12
13
14
15
resolving
symbols
credit: nand2tetris.org
34
Iterative processing
// Computes RAM[1] = 1+2+ … +RAM[0]
pseudo code
credit: nand2tetris.org
35
35
Iterative processing
// Computes RAM[1] = 1+2+ … +RAM[0]
n = R0
i = 1
sum = 0
LOOP:
if i > n goto STOP
sum = sum + i
i = i + 1
goto LOOP
STOP:
R1 = sum
pseudo code
credit: nand2tetris.org
36
36
Iterative processing
// Computes RAM[1] = 1+2+ … +RAM[0]
n = R0
i = 1
sum = 0
…
pseudo code
// Program: Sum1toN.asm
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
assembly code
credit: nand2tetris.org
37
37
Iterative processing
// Computes RAM[1] = 1+2+ … +RAM[0]
n = R0
i = 1
sum = 0
…
pseudo code
// Program: Sum1toN.asm
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
…
assembly code
credit: nand2tetris.org
38
38
// Computes RAM[1] = 1+2+ … +RAM[0]
n = R0
i = 1
sum = 0
…
Iterative processing
pseudo code
// Program: Sum1toN.asm
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
…
assembly code
32767
@0
D=M
0
1
Memory
@16 // @n
M=D
2
3
@17 // @i
M=1
4
5
@18 // @sum
M=0
6
7
…
8
9
10
11
12
13
14
15
Variables are allocated to consecutive RAM locations from address
16 onward
credit: nand2tetris.org
39
39
// Computes RAM[1] = 1+2+ … +RAM[0]
n = R0
i = 1
sum = 0
…
Iterative processing
pseudo code
credit: nand2tetris.org
40
40
Iterative processing
pseudo code
// Computes RAM[1] = 1+2+ … +RAM[0]
n = R0
i = 1
sum = 0
LOOP:
if i > n goto STOP
sum = sum + i
i = i + 1
goto LOOP
STOP:
R1 = sum
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
assembly program
credit: nand2tetris.org
41
41
Iterative processing
pseudo code
// Computes RAM[1] = 1+2+ … +RAM[0]
n = R0
i = 1
sum = 0
LOOP:
if i > n goto STOP
sum = sum + i
i = i + 1
goto LOOP
STOP:
R1 = sum
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
(LOOP)
@i
D=M
@n
D=D-M
@STOP
D;JGT // if i > n goto STOP
@sum
D=M
@i
D=D+M
@sum
M=D // sum = sum + i
@i
M=M+1 // i = i + 1
@LOOP
0;JMP
assembly program
credit: nand2tetris.org
42
42
Iterative processing
pseudo code
// Computes RAM[1] = 1+2+ … +RAM[0]
n = R0
i = 1
sum = 0
LOOP:
if i > n goto STOP
sum = sum + i
i = i + 1
goto LOOP
STOP:
R1 = sum
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
(LOOP)
@i
D=M
@n
D=D-M
@STOP
D;JGT // if i > n goto STOP
@sum
D=M
@i
D=D+M
@sum
M=D // sum = sum + i
@i
M=M+1 // i = i + 1
@LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = sum
assembly program
credit: nand2tetris.org
43
43
Iterative processing
pseudo code
// Computes RAM[1] = 1+2+ … +RAM[0]
n = R0
i = 1
sum = 0
LOOP:
if i > n goto STOP
sum = sum + i
i = i + 1
goto LOOP
STOP:
R1 = sum
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
(LOOP)
@i
D=M
@n
D=D-M
@STOP
D;JGT // if i > n goto STOP
@sum
D=M
@i
D=D+M
@sum
M=D // sum = sum + i
@i
M=M+1 // i = i + 1
@LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = sum
(END)
@END
0;JMP
assembly program
credit: nand2tetris.org
44
44
Program execution
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
(LOOP)
@i
D=M
@n
D=D-M
@STOP
D;JGT // if i > n goto STOP
@sum
D=M
@i
D=D+M
@sum
M=D // sum = sum + i
@i
M=M+1 // i = i + 1
@LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = sum
(END)
@END
0;JMP
assembly program
credit: nand2tetris.org
45
45
Program execution
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
(LOOP)
@i
D=M
@n
D=D-M
@STOP
D;JGT // if i > n goto STOP
@sum
D=M
@i
D=D+M
@sum
M=D // sum = sum + i
@i
M=M+1 // i = i + 1
@LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = sum
(END)
@END
0;JMP
assembly program
iterations
0
RAM[0]: 3
n: 3
i: 1
sum: 0
credit: nand2tetris.org
46
46
Program execution
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
(LOOP)
@i
D=M
@n
D=D-M
@STOP
D;JGT // if i > n goto STOP
@sum
D=M
@i
D=D+M
@sum
M=D // sum = sum + i
@i
M=M+1 // i = i + 1
@LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = sum
(END)
@END
0;JMP
assembly program
iterations
0 1
RAM[0]: 3
n: 3
i: 1 2
sum: 0 1
credit: nand2tetris.org
47
47
Program execution
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
(LOOP)
@i
D=M
@n
D=D-M
@STOP
D;JGT // if i > n goto STOP
@sum
D=M
@i
D=D+M
@sum
M=D // sum = sum + i
@i
M=M+1 // i = i + 1
@LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = sum
(END)
@END
0;JMP
assembly program
iterations
0 1 2
RAM[0]: 3
n: 3
i: 1 2 3
sum: 0 1 3
credit: nand2tetris.org
48
48
Program execution
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
(LOOP)
@i
D=M
@n
D=D-M
@STOP
D;JGT // if i > n goto STOP
@sum
D=M
@i
D=D+M
@sum
M=D // sum = sum + i
@i
M=M+1 // i = i + 1
@LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = sum
(END)
@END
0;JMP
assembly program
iterations
0 1 2 3
RAM[0]: 3
n: 3
i: 1 2 3 4
sum: 0 1 3 6
credit: nand2tetris.org
49
49
Program execution
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
(LOOP)
@i
D=M
@n
D=D-M
@STOP
D;JGT // if i > n goto STOP
@sum
D=M
@i
D=D+M
@sum
M=D // sum = sum + i
@i
M=M+1 // i = i + 1
@LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = sum
(END)
@END
0;JMP
assembly program
iterations
0 1 2 3 …
RAM[0]: 3
n: 3
i: 1 2 3 4 …
sum: 0 1 3 6 …
credit: nand2tetris.org
50
50
Writing assembly programs
// Computes RAM[1] = 1+2+ … +n
// Usage: put a number (n) in RAM[0]
@R0
D=M
@n
M=D // n = R0
@i
M=1 // i = 1
@sum
M=0 // sum = 0
(LOOP)
@i
D=M
@n
D=D-M
@STOP
D;JGT // if i > n goto STOP
@sum
D=M
@i
D=D+M
@sum
M=D // sum = sum + i
@i
M=M+1 // i = i + 1
@LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = sum
(END)
@END
0;JMP
assembly program
Best practice:
Design the program using pseudo code
Write the program in assembly language
Test the program (on paper) using
a variable-value trace table
credit: nand2tetris.org
51
51
OUTLINE
Hack programming
Part 1: registers and memory
Part 2: branching, variables, iteration
Part 3: pointers, input/output
Project 4 overview
52
Pointers
Example:
// for (i=0; i
RAM[addr] = -1 // 1111111111111111
// advances to the next row
addr = addr + 32
i = i + 1
goto LOOP
END:
goto END
Pseudo code
physical screen
screen memory map
16 black pixels, corresponding to the rectangle’s first row
credit: nand2tetris.org
65
65
Handling the screen (example)
// Program: Rectangle.asm
// Draws a filled rectangle at the
// screen’s top left corner, with
// width of 16 pixels and height of
// RAM[0] pixels.
// Usage: put a non-negative number
// (rectangle’s height) in RAM[0].
@SCREEN
D=A
@addr
M=D // addr = 16384
// (screen’s base address)
@0
D=M
@n
M=D // n = RAM[0]
@i
M=0 // i = 0
(LOOP)
@i
D=M
@n
D=D-M
@END
D;JGT // if i>n goto END
@addr
A=M
M=-1 // RAM[addr]=1111111111111111
@i
M=M+1 // i = i + 1
@32
D=A
@addr
M=D+M // addr = addr + 32
@LOOP
0;JMP // goto LOOP
(END)
@END // program’s end
0;JMP // infinite loop
Assembly code
(continued)
credit: nand2tetris.org
66
66
// Program: Rectangle.asm
// Draws a filled rectangle at the
// screen’s top left corner, with
// width of 16 pixels and height of
// RAM[0] pixels.
// Usage: put a non-negative number
// (rectangle’s height) in RAM[0].
@SCREEN
D=A
@addr
M=D // addr = 16384
// (screen’s base address)
@0
D=M
@n
M=D // n = RAM[0]
@i
M=0 // i = 0
Handling the screen (example)
(LOOP)
@i
D=M
@n
D=D-M
@END
D;JGT // if i>n goto END
@addr
A=M
M=-1 // RAM[addr]=1111111111111111
@i
M=M+1 // i = i + 1
@32
D=A
@addr
M=D+M // addr = addr + 32
@LOOP
0;JMP // goto LOOP
(END)
@END // program’s end
0;JMP // infinite loop
(continued)
Assembly code
credit: nand2tetris.org
67
67
Input
data
memory
(16K)
0
24,576
Hello, world
screen memory map
(8K)
16,384
Hack RAM
Hack language convention:
SCREEN: base address of the screen memory map
SCREEN
credit: nand2tetris.org
68
Input
data
memory
(16K)
0
keyboard map
24,576
Hello, world
screen memory map
(8K)
16,384
Hack RAM
Hack language convention:
SCREEN: base address of the screen memory map
KBD: address of the keyboard memory map
SCREEN
KBD
credit: nand2tetris.org
69
Handling the keyboard
To check which key is currently pressed:
Read the contents of RAM[24576] (address KBD)
If the register contains 0, no key is pressed
Otherwise, the register contains the scan code of the currently pressed key.
24576
k
Scan-code of ‘k’ = 75
0000000001001011
Hack RAM
credit: nand2tetris.org
70
Complete program example
// Adds 1+…+100.
into i = 1;
into sum = 0;
while (i <= 100){
sum += i;
i++;
}
C language code:
// Adds 1+...+100.
@i // i refers to some RAM location
M=1 // i=1
@sum // sum refers to some RAM location
M=0 // sum=0
(LOOP)
@i
D=M // D = i
@100
D=D-A // D = i - 100
@END
D;JGT // If (i-100) > 0 goto END
@i
D=M // D = i
@sum
M=D+M // sum += i
@i
M=M+1 // i++
@LOOP
0;JMP // Got LOOP
(END)
@END
0;JMP // Infinite loop
Hack assembly code:
Hack assembly convention:
Variables: lower-case
Labels: upper-case
Commands: upper-case
Credit: www.nand2tetris.org
71
71
Assembler
Credit: www.nand2tetris.org
72
Q: Who does all the “automatic” assignments of symbols to RAM addresses?
A: The assembler, which is the program that translates symbolic Hack
programs into binary Hack program. As part of the translation process, the symbols are resolved to RAM addresses. (more about this in future lectures)
Perspective
Hack is a simple machine language
User friendly syntax: D=D+A instead of ADD D,D,A
Hack is a “½-address machine”: any operation that needs to operate on the RAM must be specified using two commands: an A-command to address the RAM, and a subsequent C-command to operate on it
A Hack assembler is needed and will be discusses and developed later in the course.
Credit: www.nand2tetris.org
73
73
End notes
for (i=0; i