Uploaded by Tolu Adesanya

barnes compsys

advertisement
CO5570: The Assembler
David Barnes
Chapter 6
Slides support chapter 6 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 1
CO5570: Computer Systems: assessments
Some Java features to brush up on:
• Java packages: writing and running code within a package.
• Java enumerated types (enum).
• Running Java programs from the command line.
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 2
2
Nand to Tetris: the big picture
human
thought
write a
program
software hierarchy
abstraction
compiler
high-level
language
abstraction
OS
VM
translator
VM code
abstraction
machine
language
assembler
abstraction
digital
design
computer
architecture
p4
hardware platform
abstraction
p5
p6
CPU, RAM,
chipset
comb. and
seq. Logic
abstraction
p2
p3
elementary
logic gates
combinational
logic
p1
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Nand
Slide 3
Assembly process
Assembly Language
Machine Language
@i
M=1 // i = 1
@sum
M=0 // sum = 0
(LOOP)
@i
// if i>RAM[0]
D=M // GOTP WRITE
@R0
D=D-M
@WRITE
D;JGT
... // Etc.
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
...
assembler
run
assemble
mario.asm
into
mario.bin
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 4
Assembler: lecture plan
• The assembly process
• The Hack assembly language
• The assembly process: instructions
• The assembly process: symbols
• Developing an assembler
• Project 6 overview
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 5
The translator’s challenge (overview)
Hack assembly code
(source language)
// Computes RAM[1]=1+...+RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
...
Hack binary code
(source language)
Assembler
What are the rules
of the game?
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
...
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 6
The translator’s challenge (overview)
Hack assembly code
(source language)
// Computes RAM[1]=1+...+RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
...
Hack binary code
(source language)
Assembler
Based on the syntax
rules of:
• The source language
• The target language
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
...
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 7
Hack language specification: A-instruction
Symbolic syntax:
@ value
Examples:
@21
@foo
Where value is either
• a non-negative decimal constant or
• a symbol referring to such a constant
Binary syntax:
0 valueInBinary
Example:
0000000000010101
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 8
Hack language specification: C-instruction
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 9
Hack language specification: C-instruction
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Unconditional jump
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 10
Hack language specification: symbols
Pre-defined symbols:
symbol
value
symbol
value
R0
R1
R2
...
R15
0
1
2
...
15
SP
LCL
ARG
THIS
THAT
0
1
2
3
4
SCREEN
16384
KBD
24576
Label declaration:
(label)
Variable declaration:
@variableName
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 11
The Hack language: a translator’s perspective
Assembly program
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Assembly program elements:
• White space
Empty lines / indentation
q Line comments
q In-line comments
q
• Instructions
A-instructions
q C-instructions
q
• Symbols
References
q Label declarations
q
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 12
The Hack language: a translator’s perspective
Assembly program
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Hack machine code
Assembler
Tasks:
Handling…
• White space
• Instructions
• Symbols
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
0000000000010001
1111110000010000
0000000000000001
1110001100001000
0000000000010110
1110101010000111
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 13
Symbols
Program with symbols
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Tasks:
Handling…
• White space
• Instructions
• Symbols
Simplifying assumption:
Let’s deal with symbols later.
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 14
Handling programs without symbols
Hack machine code
Assembly program (without symbols)
// Computes RAM[1] = 1 + ... + RAM[0]
@16
M=1
// i = 1
@17
M=0
// sum = 0
@16
// if i>RAM[0] goto STOP
D=M
@0
D=D-M
@18
D;JGT
@16
// sum += i
D=M
@17
M=D+M
@16
// i++
M=M+1
@4
// goto LOOP
0;JMP
@17
D=M
@1
M=D
// RAM[1] = the sum
@22
0;JMP
Assembler
for symbol-less
Hack programs
Tasks:
Handling…
• White space
• Instructions
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
0000000000010001
1111110000010000
0000000000000001
1110001100001000
0000000000010110
1110101010000111
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 15
Handling white space
Hack machine code
Assembly program (without symbols)
// Computes RAM[1] = 1 + ... + RAM[0]
@16
M=1
// i = 1
@17
M=0
// sum = 0
@16
// if i>RAM[0] goto STOP
D=M
@0
D=D-M
@18
D;JGT
@16
// sum += i
D=M
@17
M=D+M
@16
// i++
M=M+1
@4
// goto LOOP
0;JMP
@17
D=M
@1
M=D
// RAM[1] = the sum
@22
0;JMP
Assembler
for symbol-less
Hack programs
Tasks:
Handling…
• White space
• Instructions
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
0000000000010001
1111110000010000
0000000000000001
1110001100001000
0000000000010110
1110101010000111
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 16
Handling white space
Hack machine code
Assembly program (without symbols)
// Computes RAM[1] = 1 + ... + RAM[0]
@16
M=1
// i = 1
@17
M=0
// sum = 0
@16
// if i>RAM[0] goto STOP
D=M
@0
D=D-M
@18
D;JGT
@16
// sum += i
D=M
@17
M=D+M
@16
// i++
M=M+1
@4
// goto LOOP
0;JMP
@17
D=M
@1
M=D
// RAM[1] = the sum
@22
0;JMP
Assembler
for symbol-less
Hack programs
Tasks:
Handling…
• White space
• Instructions
Handling white
space:
Ignore it!
Possible because it
isn’t used as a
separator.
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
0000000000010001
1111110000010000
0000000000000001
1110001100001000
0000000000010110
1110101010000111
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 17
Handling instructions
Hack machine code
Assembly program (without symbols)
@16
M=1
@17
M=0
@16
D=M
@0
D=D-M
@18
D;JGT
@16
D=M
@17
M=D+M
@16
M=M+1
@4
0;JMP
@17
D=M
@1
M=D
@22
0;JMP
Assembler
for symbol-less
Hack programs
Tasks:
Handling…
ü White space
• Instructions
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
0000000000010001
1111110000010000
0000000000000001
1110001100001000
0000000000010110
1110101010000111
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 18
Translating A-instructions
Symbolic syntax:
@ value
Examples:
@21
@foo
Where value is either
• a non-negative decimal constant or
• a symbol referring to such a constant (later)
Binary syntax:
0 valueInBinary
if(line.charAt(0) == '@') {
value = line.substring(1);
}
Example:
0000000000010101
Translation to binary:
• If value is a decimal constant, generate the equivalent binary constant
• If value is a symbol, later.
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 19
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
1 1 assign
1 1 1
M
0 0 1 RAM[A]
int
= line.indexOf('=');
1 1 0 1 0
D
0 1 0 D register
int
0 1 semi
1 0 0 = line.indexOf(';');
MD
0 1 1 RAM[A] and D register
1 0 Extract
0 0 0
//
substrings
…
A
1 0(simplified!)
0 A register
0 1 1 = 0 line.substring(0,
1
A register and RAM[A]
AM
1 0 1 assign);
dest
1 0 0 0 1
AD
1 1 0 A register and D register
comp
semi);
0 1 1 = 1 line.substring(assign+1,
1
AMD
1 1 1 A register, RAM[A], and D register
1 0 0 = 1 line.substring(semi+1);
1
jump
1 1 1 1 1
jump j1 j2 j3 effect:
1
0
1
0
1
0
0
1
Symbolic:
Example:
dest
d1 d2 d3 effect: the value is stored in:
//
C-instruction.
0 1 Decompose
0 1 0
null
0 0 0 The value is not stored
c1 c2 c3 c4 c5 c6
0
1
0
0
0
0
0
0
1
1
0
0
0
1
0
1
1
1
1
1
1
1
0
0
1
0
0
0
1
1
0
1
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Map<String, String> comps;
comps.put("0", "0101010");
…
comps.put("D+1", "0011111");
…
Unconditional jump
Binary:
MD=D+1
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 20
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
Symbolic:
Example:
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Unconditional jump
Binary:
MD=D+1
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 21
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Symbolic:
Binary:
MD=D+1
111
Unconditional jump
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 22
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Symbolic:
Binary:
MD=D+1
111
Unconditional jump
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 23
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Symbolic:
Binary:
MD=D+1
111
Unconditional jump
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 24
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Symbolic:
Binary:
MD=D+1
111
Unconditional jump
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 25
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Symbolic:
Binary:
MD=D+1
1110011111
Unconditional jump
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
bits = comps.get(comp);
instr += bits;
Slide 26
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Symbolic:
Binary:
MD=D+1
1110011111
Unconditional jump
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 27
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Symbolic:
Binary:
MD=D+1
1110011111
Unconditional jump
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 28
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Symbolic:
Binary:
MD=D+1
1110011111
Unconditional jump
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 29
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Unconditional jump
Symbolic:
Binary:
MD=D+1
1110011111011
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
bits = dests.get(dest);
instr += bits;
Slide 30
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Unconditional jump
Symbolic:
Binary:
MD=D+1
1110011111011
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 31
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Unconditional jump
Symbolic:
Binary:
MD=D+1
1110011111011
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 32
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Unconditional jump
Symbolic:
Binary:
MD=D+1
1110011111011
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 33
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Unconditional jump
Symbolic:
Binary:
MD=D+1
1110011111011000
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
bits = jumps.get(jump);
instr += bits;
Slide 34
Translating C-instructions
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
Example:
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
dest
null
M
D
MD
A
AM
AD
AMD
d1 d2 d3 effect: the value is stored in:
0 0 0 The value is not stored
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
RAM[A]
D register
RAM[A] and D register
A register
A register and RAM[A]
A register and D register
A register, RAM[A], and D register
jump j1 j2 j3 effect:
null
0
0
0
no jump
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
if out > 0 jump
if out = 0 jump
if out ≥ 0 jump
if out < 0 jump
if out ≠ 0 jump
if out ≤ 0 jump
Unconditional jump
Symbolic:
Binary:
MD=D+1
1110011111011000
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 35
The overall assembly logic
Assembly program
@16
M=1
@17
M=0
@16
D=M
@0
D=D-M
@18
D;JGT
@16
D=M
@17
M=D+M
@16
M=M+1
@4
0;JMP
@17
D=M
@1
M=D
@22
0;JMP
For each instruction
•
Parse the instruction:
break it into its underlying fields
•
A-instruction:
translate the decimal value into a binary value
•
C-instruction:
for each field in the instruction, generate the
corresponding binary code;
•
Assemble the translated binary codes into a complete
16-bit machine instruction
•
Write the 16-bit instruction to the output file.
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 36
The overall assembly logic
Assembly program
Hack machine code
@16
M=1
@17
M=0
@16
D=M
@0
D=D-M
@18
D;JGT
@16
D=M
@17
M=D+M
@16
M=M+1
@4
0;JMP
@17
D=M
@1
M=D
@22
0;JMP
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
0000000000010001
1111110000010000
0000000000000001
1110001100001000
0000000000010110
1110101010000111
Resulting code:
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 37
The overall assembly logic
Assembly program
Hack machine code
@16
M=1
@17
M=0
@16
D=M
@0
D=D-M
@18
D;JGT
@16
D=M
@17
M=D+M
@16
M=M+1
@4
0;JMP
@17
D=M
@1
M=D
@22
0;JMP
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
0000000000010001
1111110000010000
0000000000000001
1110001100001000
0000000000010110
1110101010000111
Resulting code:
Disclaimer
The source code
contains no symbols
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 38
Assembler: lecture plan
• Assembler logic (basic)
• The Hack assembly language
• The assembly process: instructions
• The assembly process: symbols
• Developing an assembler
• Project 6 overview
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 39
Hack Assembler
Assembly program
Hack machine code
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Assembler
Tasks:
Handling…
• White space
•
Instructions
•
Symbols
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
0000000000010001
1111110000010000
0000000000000001
1110001100001000
0000000000010110
1110101010000111
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 40
Hack Assembler
Assembly program
Hack machine code
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Assembler
Tasks:
Handling…
ü White space
ü Instructions
•
Symbols
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
0000000000010001
1111110000010000
0000000000000001
1110001100001000
0000000000010110
1110101010000111
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 41
Handling symbols
Assembly program
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Pre-defined symbols:
• represent special memory locations
label symbols:
• represent destinations of
goto instructions
variable symbols:
• represent memory locations where the
programmer wants to maintain values
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 42
Handling pre-defined symbols
Assembly program
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
The Hack language specification
describes 23 pre-defined symbols:
symbol
value
symbol
value
R0
R1
R2
...
R15
SCREEN
KBD
0
1
2
...
15
16384
24576
SP
LCL
ARG
THIS
THAT
0
1
2
3
4
Translating @preDefinedSymbol :
Replace preDefinedSymbol with its value.
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 43
Handling symbols that denote labels
Assembly program
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Label symbols
• Used to label destinations of goto
commands
• Declared by the pseudo-command (XXX)
• This directive defines the symbol XXX
to refer to the memory location holding the
next instruction in the program
if(line.charAt(0) == '(') {
label = line.substring(1, line.length() – 1);
value label into symbol table for the
symbol
// Insert
LOOPnext instruction
4
//
address.
STOP
18
…
END
22
}
Translating @labelSymbol :
Replace labelSymbol with its value
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 44
Handling symbols that denote variables
Assembly program
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Variable symbols
• Any symbol XXX appearing in an
assembly program which is not predefined and is not defined elsewhere
using the (XXX) directive is treated as
a variable
• Each variable is assigned a unique
memory address, starting at 16
symbol
value
i
sum
16
17
Translating @variableSymbol :
• If seen for the first time,
assign a unique memory address
• Replace variableSymbol with this address
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 45
Symbol table
Assembly program
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 46
Symbol table
Assembly program
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
Symbol table
symbol
value
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 47
Symbol table
Assembly program
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Symbol table
symbol
value
R0
0
R1
R2
...
R15
SCREEN
KBD
SP
LCL
ARG
THIS
THAT
1
2
...
15
16384
24576
0
1
2
3
4
Initialization:
Add the pre-defined
symbols
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 48
Symbol table
Assembly program
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Symbol table
symbol
value
R0
0
R1
R2
...
R15
SCREEN
KBD
SP
LCL
ARG
THIS
THAT
1
2
...
15
16384
24576
0
1
2
3
4
Initialization:
Add the pre-defined
symbols
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 49
Symbol table
Assembly program
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Symbol table
symbol
value
R0
0
R1
R2
...
R15
SCREEN
KBD
SP
LCL
ARG
THIS
THAT
LOOP
STOP
END
1
2
...
15
16384
24576
0
1
2
3
4
4
18
22
Initialization:
Add the pre-defined
symbols
First pass:
Add the label symbols
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 50
Symbol table
Assembly program
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Symbol table
symbol
value
R0
0
R1
R2
...
R15
SCREEN
KBD
SP
LCL
ARG
THIS
THAT
LOOP
STOP
END
1
2
...
15
16384
24576
0
1
2
3
4
4
18
22
Initialization:
Add the pre-defined
symbols
First pass:
Add the label symbols
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 51
Symbol table
Assembly program
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Symbol table
symbol
value
R0
0
R1
R2
...
R15
SCREEN
KBD
SP
LCL
ARG
THIS
THAT
LOOP
STOP
END
i
sum
1
2
...
15
16384
24576
0
1
2
3
4
4
18
22
16
17
Initialization:
Add the pre-defined
symbols
First pass:
Add the label symbols
Second pass:
Add the var. symbols
Usage:
To resolve a symbol, look up its value
in the symbol table
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 52
The assembly process
Initialization:
q
q
Construct an empty symbol table
Add the pre-defined symbols to the symbol table
First pass:
Scan the entire program;
For each “instruction” of the form (xxx):
q Add the pair (xxx, address) to the symbol table,
where address is the number of the instruction following (xxx)
Second pass:
Set n to 16
Scan the entire program again; for each instruction:
q If the instruction is @symbol, look up symbol in the symbol table;
• If (symbol, value) is found, use value to complete the instruction’s translation;
• If not found:
o Add (symbol, n) to the symbol table,
o Use n to complete the instruction’s translation,
o n++
q If the instruction is a C-instruction, complete the instruction’s translation
q Write the translated instruction to the output file.
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 53
Hack Assembler
Assembly program
// Computes RAM[1] = 1 + ... + RAM[0]
@i
M=1
// i = 1
@sum
M=0
// sum = 0
(LOOP)
@i
// if i>RAM[0] goto STOP
D=M
@R0
D=D-M
@STOP
D;JGT
@i
// sum += i
D=M
@sum
M=D+M
@i
// i++
M=M+1
@LOOP // goto LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D // RAM[1] = the sum
(END)
@END
0;JMP
Hack machine code
Assembler
Challenges:
Handling…
ü White space
ü Instructions
ü Symbols
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
0000000000010001
1111110000010000
0000000000000001
1110001100001000
0000000000010110
1110101010000111
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 54
Assembler: lecture plan
• Assembler logic (basic)
• The Hack assembly language
• The assembly process: instructions
• The assembly process: symbols
• Developing an assembler
• Project 6 overview
The assessment will be related to the task of
writing an assembler but will be different.
The remaining slides have been left in place for consistency with the course text book but we will
not be covering them directly in the course.
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 55
Sub-tasks that need to be done
• Reading and parsing commands
• Converting mnemonics à code
• Handling symbols
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 56
Reading and Parsing Commands
No need to understand
the meaning of anything
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 57
Reading and Parsing Commands
• Start reading a file with a given name
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 58
Reading and Parsing Commands
• Start reading a file with a given name
q
q
E.g. Constructor for a Parser object that accepts a string
specifying a file name.
Need to know how to read text files
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 59
Reading and Parsing Commands
• Start reading a file with a given name
• Move to the next command in the file
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 60
Reading and Parsing Commands
• Start reading a file with a given name
• Move to the next command in the file
q
Are we finished?
q
Get the next command: void advance()
q
Need to read one line at a time
q
Need to skip whitespace including comments
boolean hasMoreCommands()
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 61
Reading and Parsing Commands
• Start reading a file with a given name
• Move to the next command in the file
• Get the fields of the current command
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 62
Reading and Parsing Commands
• Start reading a file with a given name
• Move to the next command in the file
• Get the fields of the current command
q
Type of current command (A-Command, C-Command, or Label)
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 63
Reading and Parsing Commands
• Start reading a file with a given name
• Move to the next command in the file
• Get the fields of the current command
q
Type of current command (A-Command, C-Command, or Label)
q
Easy access to the fields:
D=M+1; JGT
D
M +
1
@sum
J
G
T
s
u
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
m
Slide 64
Reading and Parsing Commands
• Start reading a file with a given name
• Move to the next command in the file
• Get the fields of the current command
q
Type of current command (A-Command, C-Command, or Label)
q
Easy access to the fields:
D=M+1; JGT
D
String dest();
M +
1
String comp();
@sum
J
G
T
String jump();
s
u
m
String label();
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 65
Translating Mnemonic to Code: overview
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 66
Translating Mnemonic to Code: overview
No need to worry about
how the mnemonic fields
were obtained
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 67
Translating Mnemonic to Code: destination
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
dest
d1 d2 d3
null
M
D
MD
A
AM
AD
AMD
0
0
0
0
1
1
1
1
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
0
0
1
1
0
0
1
1
0
1
0
1
0
1
0
1
Slide 68
Translating Mnemonic to Code: jump
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
jump j1 j2 j3
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
null
0
0
0
JGT
JEQ
JGE
JLT
JNE
JLE
JMP
0
0
0
1
1
1
1
0
1
1
0
0
1
1
1
0
1
0
1
0
1
Slide 69
Translating Mnemonic to Code: computation
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
comp
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
a=0
c1 c2 c3 c4 c5 c6
M
!M
-M
M+1
M-1
D+M
D-M
M-D
D&M
D|M
a=1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
0
1
1
1
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
1
1
0
0
0
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
0
1
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 70
Recap: Parsing + Translating
Symbolic syntax:
dest = comp ; jump
Binary syntax:
1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3
// Assume that current command is
//
D = M+1; JGT
String c=parser.comp();
String d=parser.dest();
String j=parser.jump();
// “M+1”
// “D”
// “JGT”
String cc = Code.comp(c);
String dd = Code.dest(d);
String jj = Code.jump(j);
// “1110111”
// “010”
// “001”
String out = “111” + cc + dd + jj;
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 71
The Symbol Table
Symbol
Address
loop
73
sum
12
No need to worry about
what these symbols mean
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 72
The Symbol Table
Symbol
Address
loop
73
sum
12
• Create an new empty table
• Add a (symbol , address) pair to the table
• Does the table contain a given symbol?
• What is the address associated with a given symbol?
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 73
Using the Symbol Table
• Create a new empty table
• Add all the pre-defined symbols to the table
• While reading the input, add labels and new variables to the table
• Whenever you see a “@xxx” command, where xxx is not a number,
consult the table to replace the symbol xxx with its address.
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 74
Using the Symbol Table: adding symbols
• …
• …
• While reading the input, add labels and new variables to the table
q
q
Labels: when you see a “(xxx)” command, add the symbol xxx
and the address of the next machine language command
• Comment 1: this requires maintaining this running address
• Comment 2: this may need to be done in a first pass
Variables: when you see an “@xxx” command, where xxx is not a
number and not already in the table, add the symbol xxx and the
next free address for variable allocation
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 75
Overall logic
• Initialization
q
Of Parser
q
Of Symbol Table
• First Pass: Read all commands, only paying attention to labels and
updating the symbol table
• Restart reading and translating commands
• Main Loop:
q
Get the next Assembly Language Command and parse it
q
For A-commands: Translate symbols to binary addresses
q
For C-commands: get code for each part and put them together
q
Output the resulting machine language command
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 76
Parser module: proposed API
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 77
Code module: proposed API
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 78
SymbolTable module: proposed API
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 79
Assembler: lecture plan
• The assembly process
• The Hack assembly language
• The assembly process: instructions
• The assembly process: symbols
• Developing an assembler
• Project 6 overview
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 80
Developing a Hack Assembler
Contract
• Develop an assembler that translates Hack assembly programs into executable
Hack binary code
• The source program is supplied in a text file named Xxx.asm
• The generated code is written into a text file named Xxx.hack
• Assumption: Xxx.asm is error-free
Usage
prompt> java HackAssembler Xxx.asm
This command should create a new Xxx.hack file that can be executed as-is on
the Hack computer.
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 81
Proposed design
The assembler can be implemented in any high-level language
Proposed software design
q
Parser: unpacks each instruction into its underlying fields
q
Code: translates each field into its corresponding binary value
q
SymbolTable: manages the symbol table
q
Main: initializes I/O files and drives the process.
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 82
Proposed Implementation
Staged development
• Develop a basic assembler that can translate assembly programs without
symbols
• Develop an ability to handle symbols
• Morph the basic assembler into an assembler that can translate any assembly
program
Supplied test programs
Add.asm
Max.asm
MaxL.asm
Rectangle.asm
RectangleL.asm
Pong.asm
PongL.asm
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 83
Test program: Add
Add.asm
// Computes RAM[0] = 2 + 3
@2
D=A
@3
D=D+A
@0
M=D
Basic test of handling:
• White space
• Instructions
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 84
Test program: Max
Max.asm
// Computes RAM[2] = max(RAM[0],RAM[1])
@R0
D=M
@R1
D=D-M
@OUTPUT_RAM0
D;JGT
// D = RAM[0]
MaxL.asm
// Symbol-less version
// D = RAM[0] - RAM[1]
@0
D=M
// D = RAM[0]
// if D>0 goto output RAM[0] @1
D=D-M
// D = RAM[0] - RAM[1]
// Output RAM[1]
@12
@R1
D;JGT
// if D>0 goto output RAM[0]
D=M
@R2
// Output RAM[1]
M=D
// RAM[2] = RAM[1]
@1
@END
D=M
0;JMP
@2
M=D
// RAM[2] = RAM[1]
(OUTPUT_RAM0)
@16
@R0
0;JMP
D=M
@R2
@0
M=D
// RAM[2] = RAM[0]
D=M
@2
(END)
M=D
// RAM[2] = RAM[0]
@END
0;JMP
@16
0;JMP
with
labels
without
labels
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 85
Test program: Rectangle
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 86
Test program: Rectangle
Rectangle.asm
// Rectangle.asm
@R0
D=M
@n
M=D
// n = RAM[0]
@i
M=0
// i = 0
RectangleL.asm
// Symbol-less version
@SCREEN
D=A
@address
M=D // base address of the Hack screen
(LOOP)
@i
D=M
@n
D=D-M
@END
D;JGT
...
with
symbols
// if i>n goto END
@0
D=M
@16
M=D
// n = RAM[0]
@17
M=0
// i = 0
@16384
D=A
@18
M=D
// base address of the Hack screen
@17
D=M
@16
D=D-M
@27
D;JGT
...
without
symbols
// if i>n goto END
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 87
Test program: Pong
CPU Emulator
Pong
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 88
Test program: Pong
Pong.asm
// Pong.asm
@256
D=A
@SP
M=D
@133
0;JMP
@R15
M=D
@SP
AM=M-1
D=M
A=A-1
D=M-D
M=0
@END_EQ
D;JNE
@SP
A=M-1
M=-1
(END_EQ)
@R15
A=M
0;JMP
@R15
M=D
...
Observations:
• Source code originally written in the Jack language
• The Hack code was generated by the Jack compiler and
the Hack assembler
• The resulting code is 28,374 instructions long
• (includes the Jack OS)
Machine generated code:
• No white space
• “Strange” addresses
• “Strange” labels
• “Strange” pre-defined symbols
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 89
Testing options
Use your assembler to translate Xxx.asm,
generating the executable file Xxx.hack
Hardware simulator:
load Xxx.hack into the Hack Computer chip, then execute it
CPU Emulator:
load Xxx.hack into the supplied CPUEmulator, then execute it
Assembler:
use the supplied Assembler to translate Xxx.asm;
Compare the resulting code to the binary code generated by your assembler.
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 90
Testing your assembler using the supplied assembler
Xxx.hack file,
translated by
the supplied
assembler
Xxx.hack file,
translated by
your
assembler
Source
Xxx.asm
file
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 91
Project 6 Resources
All the necessary project 6 files
are available in:
nand2tetris / projects / 06
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 92
More resources
• Supplied Assembler
• Supplied CPU emulator
• Assembler Tutorial
• Proposed Assembler API
• nand2tetris Q&A forum
All available in: www.nand2tetris.org
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 93
Assembler: lecture plan
• The assembly process
• The Hack assembly language
• The assembly process: instructions
• The assembly process: symbols
• Developing an assembler
• Project 6 overview
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 94
Chapter 6
Assembler
Slides support chapter 6 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 6 / Copyright © Noam Nisan and Shimon Schocken
Slide 95
COMP5570: The Virtual Machine,
Part I
David Barnes
Chapter 7
Design of the VM
These slides support chapter 7 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The overall task
• Bridging the gap between the low-level, primitive
operations we have at machine level …
• … and the high-level way we would like to be able to
express the problems we wish to solve.
• The role of a compiler.
• In this lecture we will introduce the concept of a virtual
machine as an intermediate step in the compilation process.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The big picture
High-level program written in Jack.
/** Demo: working with Point objects */
class Main {
function void main() {
var Point p1, p2, p3;
let p1 = Point.new(1,2);
let p2 = Point.new(3,4);
let p3 = p1.plus(p2);
do p3.print(); // prints (4,6)
do Output.println();
do Output.printInt(p1.distance(p3));
return;
}
}
/** Represents a Point */
class Point {
field int x, y;
static int pointCount;
/** Constructs a new point */
constructor Point new(int ax, int ay) {
let x = ax;
let y = ay;
let pointCount = pointCount + 1;
return this;
}
...
}
(4,6)
5
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The big picture
Low-level code
High-level program
/** Demo: working with Point objects */
class Main {
function void main() {
var Point p1, p2, p3;
let p1 = Point.new(1,2);
let p2 = Point.new(3,4);
let p3 = p1.plus(p2);
do p3.print(); // prints (4,6)
do Output.println();
do Output.printInt(p1.distance(p3));
return;
}
}
/** Represents a Point */
class Point {
field int x, y;
static int pointCount;
/** Constructs a new point */
constructor Point new(int ax, int ay) {
let x = ax;
let y = ay;
let pointCount = pointCount + 1;
return this;
}
...
}
Compiler
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111110000010000
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Program compilation: 1-tier
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Program compilation: 1-tier
that
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Program compilation: 1-tier
that
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Program compilation: 1-tier
Depending on the degree of coupling between
‘front end’ source parsing and ‘back end’ code
generation, there might be some scope for
shared elements.
that
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Program compilation: 2-tier
that
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Program compilation: 2-tier
abstraction
that
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Program compilation: 2-tier
abstraction
that
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Program compilation: 2-tier
Only a single front-end is required for all
target architectures.
abstraction
that
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Jack compilation
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Jack compilation
Front end:
projects
10,11
Back end:
projects
7,8
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Jack compilation
Both emulation and full translation of VM
code are options.
virtual
machine
‘Just-in-time’ (JIT) compilation offers a hybrid
approach.
JIT actually pioneered at Kent by Peter Brown:
‘throw-away compiling’ for BASIC in the
1970s.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The big picture
Human
Thought
Write a
program
Abstraction
High Level
Language
Compiler
OS
Abstraction
VM Code
VM
translator
Abstraction
p7
p8
machine
language
Virtual Machine (chapters 7-8)
• Understanding the VM abstraction
• Building a VM implementation
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The big picture
Stack machine abstraction
• Architecture
• Commands
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack
top
Stack operations:
•
push: add an element at the stack’s top
•
pop:
remove the top element
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack
NB: the stack here grows
downwards, so the ‘top’ of the
stack appears visually to move
down as items are pushed and
up as items are popped.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack
NB: the stack here grows
downwards, so the ‘top’ of the
stack appears visually to move
down as items are pushed and
up as items are popped.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack
NB: the stack here grows
downwards, so the ‘top’ of the
stack appears visually to move
down as items are pushed and
up as items are popped.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack arithmetic
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack arithmetic
Applying a function f on the stack:
• pops the argument(s) from the stack
• Computes f on the arguments
• Pushes the result onto the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack arithmetic
Applying a function f on the stack:
• pops the argument(s) from the stack
• Computes f on the arguments
• Pushes the result onto the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack arithmetic
Applying a function f on the stack:
• pops the argument(s) from the stack
• Computes f on the arguments
• Pushes the result onto the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack arithmetic
Applying a function f on the stack:
• pops the argument(s) from the stack
• Computes f on the arguments
• Pushes the result onto the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack arithmetic
Applying a function f on the stack:
• pops the argument(s) from the stack
• Computes f on the arguments
• Pushes the result onto the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
NB: The function’s arguments are
always removed from the stack
before the operation is performed.
The operation is never performed
directly on a value in the stack.
Stack arithmetic
Applying a function f on the stack:
• pops the argument(s) from the stack
• Computes f on the arguments
• Pushes the result onto the stack.
NB: The function’s arguments are
always removed from the stack
before the operation is performed.
The operation is never performed
directly on a value in the stack.
At least, that’s the specification view,
but practical implementations might
behave differently!
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack arithmetic
Applying a function f on the stack:
• pops the argument(s) from the stack
• Computes f on the arguments
• Pushes the result onto the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack arithmetic
Applying a function f on the stack:
• pops the argument(s) from the stack
• Computes f on the arguments
• Pushes the result onto the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack arithmetic
Applying a function f on the stack:
• pops the argument(s) from the stack
• Computes f on the arguments
• Pushes the result onto the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack arithmetic
Applying a function f on the stack:
• pops the argument(s) from the stack
• Computes f on the arguments
• Pushes the result onto the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack arithmetic
Applying a function f on the stack:
• pops the argument(s) from the stack
• Computes f on the arguments
• Pushes the result onto the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack arithmetic (big picture)
high-level
x = 17 + 19
lower-level
compile
push 17
push 19
add
pop x
Abstraction / implementation
• The high-level language is an abstraction;
• It can be implemented by a stack machine.
• The stack machine is also an abstraction;
• It can implemented by... Stay tuned.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The stack machine model
Stack machine, manipulated by:
• Arithmetic / logical commands
• Memory segment commands
• Branching commands
• Function commands
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
For the time being, we are not concerned with
how the translation from Jack to VM is achieved.
push x
sub
We focus now on the VM execution model.
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
21
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
21
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
21
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
21
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
21
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic commands
VM code
// d=(2-x)+(y+9)
push 2
push x
sub
push y
push 9
add
add
pop d
21
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Logical commands
VM code
// (x<7) or (y==8)
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Logical commands
VM code
// (x<7) or (y==8)
push x
push 7
lt
push y
push 8
eq
or
NB: ‘or’ here is a fully-evaluating operator,
in contrast to Java’s short-circuit operator: ||
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Logical commands
VM code
// (x<7) or (y==8)
push x
push 7
lt
push y
push 8
eq
or
NB: ‘or’ here is a fully-evaluating operator,
in contrast to Java’s short-circuit operator: ||
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic / Logical commands
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic / Logical commands
Command
Return value
Return value
add
x+y
integer
sub
x-y
integer
neg
-y
integer
eq
x==0
boolean
gt
x>y
boolean
lt
x<y
boolean
and
x and y
boolean
or
x or y
boolean
not
not x
boolean
x
y
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic / Logical commands
Command
Return value
Return value
add
x+y
integer
sub
x-y
integer
neg
-y
integer
eq
x == y
boolean
gt
x>y
boolean
lt
x<y
boolean
and
x and y
boolean
or
x or y
boolean
not
not x
boolean
x
y
NB: <= and >= are missing.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Arithmetic / Logical commands
Command
Return value
Return value
add
x+y
integer
sub
x-y
integer
neg
-y
integer
eq
x == y
boolean
gt
x>y
boolean
lt
x<y
boolean
and
x and y
boolean
or
x or y
boolean
not
not x
boolean
x
y
NB: <= and >= are missing.
NB: Both and and or are
fully evaluating.
Observation: Any arithmetic or logical expression can be expressed and
evaluated by applying some sequence of the above operations on a stack.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The stack machine model
Stack machine, manipulated by:
• Arithmetic / logical commands
• Memory segment commands
• Branching commands
• Function commands
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The big picture
Compiled VM code
Source code (Jack)
class Foo {
...
...
static int s1, s2;
function int bar (int x, int y) {
var int a, b, c;
...
let c = s1 + y;
...
}
}
compile
...
...
...
...
...
...
...
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The big picture
Compiled VM code
Source code (Jack)
class Foo {
...
...
static int s1, s2;
function int bar (int x, int y) {
var int a, b, c;
...
let c = s1 + y;
...
}
}
compile
...
...
push s1
push y
add
pop c
...
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The big picture
Compiled VM code
Source code (Jack)
class Foo {
...
...
static int s1, s2;
function int bar (int x, int y) {
var int a, b, c;
...
let c = s1 + y;
...
}
}
compile
...
...
push s1
push y
add
pop c
...
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Variable kinds
Compiled VM code
Source code (Jack)
class Foo {
...
...
static int s1, s2;
function int bar (int x, int y) {
var int a, b, c;
...
let c = s1 + y;
compile
...
}
...
...
push s1
push y
add
pop c
...
...
}
Variable kinds
• Argument variables
• Local variables
• Static variables
• (More kinds later)
Each kind of variable arises in a different context:
• Arguments are provided by the caller.
• Locals are local to the callee.
• Statics come into existence at program startup
and persist.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Variable kinds and memory segments
Compiled VM code
Source code (Jack)
class Foo {
...
...
static int s1, s2;
function int bar (int x, int y) {
var int a, b, c;
...
compile
let c = s1 + y;
...
}
...
...
push s1
push y
add
pop c
...
...
}
Virtual memory segments:
x
y
a
b
c
s1
s2
NB: It is not uncommon for arguments and locals
to be stored on a single runtime stack but that
makes stack management more complex than this
approach.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Variable kinds and memory segments
Compiled VM code
Source code (Jack)
class Foo {
...
...
static int s1, s2;
function int bar (int x, int y) {
var int a, b, c;
...
compile
let c = s1 + y;
...
}
...
...
push static 0
push y
add
pop c
...
...
}
Virtual memory segments:
x
y
a
b
c
s1
s2
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Variable kinds and memory segments
Compiled VM code
Source code (Jack)
class Foo {
...
...
static int s1, s2;
function int bar (int x, int y) {
var int a, b, c;
...
compile
let c = s1 + y;
...
}
...
...
push static 0
push argument 1
add
pop c
...
...
}
Virtual memory segments:
x
y
a
b
c
s1
s2
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Variable kinds and memory segments
Compiled VM code
Source code (Jack)
class Foo {
...
...
static int s1, s2;
function int bar (int x, int y) {
var int a, b, c;
...
compile
let c = s1 + y;
...
}
...
...
push static 0
push argument 1
add
pop local 2
...
...
}
Virtual memory segments:
x
y
a
b
c
s1
s2
Following compilation, all
the symbolic references are
replaced with references to
virtual memory segments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Memory segments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Memory segments
The constant segment
doesn’t necessarily exist in
memory like the others.
Syntax: push / pop segment i
Examples:
•
push constant 17
•
pop local 2
•
pop static 5
•
push argument 3
•
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Memory segments
memory
memory
segments
segment
0
1
2
3
...
local
argument
this
. .... .
...
...
. .... .
...
...
...
Syntax:
push segment i
Where segment is: argument, local, static, constant,
this, that, pointer, or temp
and i is a non-negative integer.
Syntax:
pop segment i
Where segment is: argument, local, static,
this, that, pointer, or temp
and i is a non-negative integer.
that
constant
static
pointer
temp
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Quiz: write the missing code
let static 2 = argument 1
?
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The stack machine model
VM language:
• Arithmetic / logical commands
• Memory segment commands
• Branching commands
• Function commands
We will look at the branching
and function commands in
Chapter 8.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Review
• We have seen that compiling high-level source to an
intermediate form has the potential to reduce the cost of
implementing a language on a new architecture.
• Compiling different high-level languages to a common
intermediate form means a new language can be introduced
relatively quickly.
• A stack-based ‘virtual machine’ provides a good abstraction
to serve as the intermediate step in compilation of
procedural and object-oriented languages.
• The next step will be to look at translating VM instructions
to Hack assembly code.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
COMP5570: The Virtual Machine,
Part I
David Barnes
Chapter 7
Translation to Hack Asm
These slides support chapter 7 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Virtual machine
Overview
VM implementation platforms
ü The road ahead
• VM emulator
ü Program compilation
• VM translator
VM abstraction
The VM translator
ü the stack
• Proposed implementation
ü memory segments
• Building it (project 7)
VM implementation
• the stack
• memory segments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Memory segments
memory
memory
segments
segment
0
1
2
3
...
local
argument
this
that
. .... .
...
...
. .... .
...
...
...
constant
static
pointer
temp
Syntax:
push segment i
Where segment is: argument, local, static, constant,
this, that, pointer, or temp
and i is a non-negative integer.
Syntax:
pop segment i
Where segment is: argument, local, static,
this, that, pointer, or temp
and i is a non-negative integer.
NB: No pop constant. (Why not?)
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM abstraction
let static 2 = argument 1
push argument 1
pop static 2
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM stack architecture
• All of the arithmetic and logical operations depend on the existence
of a stack.
Operands pushed prior to evaluation.
q Operands popped in order to apply the operation.
q Result pushed to the stack.
q
• Function/method calling (Chapter 8) will require the use of a stack to
store return addresses.
• However! The Hack architecture does not have a stack.
• Supporting the stack abstraction will be a major part of the
translation/implementation effort.
• Limited registers (A and D) mean this requires considerable thought.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Standard VM mapping on the Hack platform
Hack RAM
Looking ahead
The Hack architecture has a single linear RAM, so the separate
segments must be realised using that.
Each segment is simulated by having a dedicated RAM location
that stores its base (LCL (RAM[1]), ARG (RAM[2]), etc.).
Segment offsets are added to the base address; e.g,
push local 2
would be translated to
push RAM[RAM[LCL] + 2]
LCL, ARG, etc. act as ‘pointers’.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Pointer manipulation
Not present in Java but common in
languages like C.
Variables containing addresses are
called pointers.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Pointer manipulation
Pseudo assembly code
Not present in Java but common in
languages like C.
D = *p
Variables containing addresses are
called pointers.
In C, * is a ‘dereferencing
operator’. *p means, access the
memory location for which p
stores the address.
Notation:
*p
// the memory location that p points at
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
‘Follow the pointer.’
Pointer manipulation
Pseudo assembly code
D = *p
// D becomes 23
In Hack:
Variables containing addresses are
called pointers.
@p
A=M
D=M
Recall that M means
RAM[A]
Notation:
*p
Not present in Java but common in
languages like C.
// the memory location that p points at
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
In C, * is a ‘dereferencing
operator’. *p means, access the
memory location for which p
stores the address.
‘Follow the pointer.’
Pointer manipulation
Pseudo assembly code
D = *p
// D becomes 23
p-D = *p
Not present in Java but common in
languages like C.
Variables containing addresses are
called pointers.
In C, * is a ‘dereferencing
operator’. *p means, access the
memory location for which p
stores the address.
Notation:
*p
// the memory location that p points at
p++
// increment: p = p + 1
p--
// decrement: p = p - 1
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
‘Follow the pointer.’
Pointer manipulation
Pseudo assembly code
D = *p
// D becomes 23
p-D = *p
// RAM[0] becomes 256
// D becomes 19
Not present in Java but common in
languages like C.
Variables containing addresses are
called pointers.
In C, * is a ‘dereferencing
operator’. *p means, access the
memory location for which p
stores the address.
Notation:
*p
// the memory location that p points at
p++
// increment: p = p + 1
p--
// decrement: p = p - 1
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
‘Follow the pointer.’
Pointer manipulation
Pseudo assembly code
D = *p
// D becomes 23
p-D = *p
// RAM[0] becomes 256
// D becomes 19
*q = 9
q++
Not present in Java but common in
languages like C.
Variables containing addresses are
called pointers.
In C, * is a ‘dereferencing
operator’. *p means, access the
memory location for which p
stores the address.
Notation:
*p
// the memory location that p points at
p++
// increment: p = p + 1
p--
// decrement: p = p - 1
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
‘Follow the pointer.’
Pointer manipulation
Pseudo assembly code
D = *p
// D becomes 23
p-D = *p
// RAM[0] becomes 256
// D becomes 19
*q = 9
q++
// RAM[1024] becomes 9
// RAM[1] becomes 1025
Notation:
*p
// the memory location that p points at
p++
// increment: p = p + 1
p--
// decrement: p = p - 1
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Not present in Java but common in
languages like C.
Variables containing addresses are
called pointers.
In C, * is a ‘dereferencing
operator’. *p means, access the
memory location for which p
stores the address.
‘Follow the pointer.’
Stack implementation
Abstraction:
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack implementation
Abstraction:
Implementation:
Assumptions:
• SP stored in RAM[0]
• Stack base addr = 256
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack implementation
Abstraction:
Logic:
*SP = 17
Implementation:
Assumptions:
SP++
Hack assembly:
• SP stored in RAM[0]
• Stack base addr = 256
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Stack implementation
Abstraction:
Logic:
*SP = 17
Implementation:
Assumptions:
SP++
Hack assembly:
• SP stored in RAM[0]
@17
• Stack base addr = 256
D=A
@SP
// D=17
// *SP=D
A=M
M=D
@SP
// SP++
M=M+1
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
How to implement push D.
Stack implementation
VM code:
push constant i
Assembly pseudo code:
VM translator
*SP = i , SP++
VM Translator
• A program that translates VM commands into lower-level commands of
some host platform (like the Hack computer)
• Each VM command generates one or more low-level commands
• The low-level commands end up realizing the stack and the memory
segments on the host platform.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Virtual machine: lecture plan
Overview
VM implementation platforms
ü The road ahead
• VM emulator
ü Program compilation
• VM translator
VM abstraction
The VM translator
ü the stack
• Proposed implementation
ü memory segments
• Building it (project 7)
VM implementation
ü the stack
• memory segments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Memory segments (abstraction)
memory
segment
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Memory segments (abstraction)
memory
segments
0
1
2
3
...
Syntax: push/pop segment i
Examples:
•
push constant 17
•
pop local 2
•
pop static 5
•
push argument 3
•
pop this 2
•
...
local
argument
this
...
...
...
...
...
...
...
...
...
that
constant
static
pointer
temp
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push/pop local i
memory
segments
0
1
2
3
...
Syntax: push/pop local i
local
argument
this
...
...
...
...
...
...
...
...
...
that
constant
static
pointer
temp
Why do we need a local segment?
When the compiler translates high-level code into VM code...
• high-level operations on local variables are translated into
VM operations on the entries of the segment local
• We now turn to describe how the local segment can be realized on the host platform.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing pop local i (example)
Abstraction:
Write it in
Hack assembly
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing pop local i (example)
Abstraction:
stack pointer
base address of
the local segment
Implementation:
the local segment
is stored somewhere in the RAM
Write it in
Hack assembly
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing pop local i (example)
Abstraction:
stack pointer
Implementation:
addr=LCL+2, SP--, *addr=*SP
base address of
the local segment
Implementation:
the local segment
is stored somewhere in the RAM
Notation is slightly
confusing because the
address is actually
RAM[LCL] + 2
or
*LCL + 2
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing pop local i
Abstraction:
i
i
stack pointer
Implementation:
addr=LCL+ i, SP--, *addr=*SP
base address of
the local segment
Hack assembly:
Implementation:
the local segment
is stored somewhere in the RAM
You write it!
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
NB: This is considerably more
complex than implementing the
push instruction.
Hint: You will probably need to
use a ‘temporary’.
Implementing push/pop local i
VM code:
Assembly pseudo code:
pop local i
addr = LCL+ i, SP--, *addr = *SP
VM Translator
push local i
addr = LCL+ i, *SP = *addr, SP++
stack pointer
base address of
the local segment
Implementation:
the local segment
is stored somewhere in the RAM
The base address of the local segment
will vary throughout the life of a
program.
It will be different for each function
called.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Memory segments
memory
segments
0
1
2
3
...
Syntax: push/pop segment i
local
argument
this
...
...
...
...
...
...
...
...
...
that
constant
static
pointer
temp
• We know how to implement push/pop local i
• We now turn to implementing push/pop operations
on the segments argument, this, and that.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push/pop local/argument/this/that i
memory
segments
0
1
2
3
...
...
...
...
Syntax: push/pop local/argument/this/that i
...
...
...
Why do we need these four segments?
...
...
When the compiler translates high-level code into VM code...
...
•
high-level operations on local variables are translated into
VM operations on the entries of the segment local
•
high-level operations on argument variables are translated into
VM operations on the entries of the segment argument
•
high-level operations on the field variables of the current object are translated into
VM operations on the entries of the segment this
•
high-level operations on array entries are translated into
VM operations on the entries of the segment that
local
argument
this
that
constant
static
pointer
temp
We now turn to describe how these four segments can be realized on the host platform.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push/pop local/argument/this/that i
VM code:
Assembly pseudo code:
push segment i
addr = segmentPointer + i, *SP = *addr, SP++
VM translator
pop segment i
addr = segmentPointer + i, SP--, *addr = *SP
segment = {local, argument, this, that}
The base addresses of all these
segments will vary throughout
the life of a program.
Host RAM
base addresses of the
four segments are
stored in these pointers
• push/pop local i
• push/pop argument i
• push/pop this i
the four segments are
stored somewhere in
the RAM
are implemented
precisely the
same way
• push/pop that i
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Memory segments
memory
segments
0
1
2
3
...
Syntax: push/pop segment i
local
argument
this
...
...
...
...
...
...
...
...
...
that
constant
static
pointer
temp
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push constant i
memory
segments
0
1
2
3
...
Syntax: push constant i
local
argument
this
...
...
...
...
...
...
...
...
...
that
constant
static
pointer
temp
Why do we need a constant segment?
Because we need to represent constants somehow in the VM level.
When the compiler translates high-level code into VM code...
• high-level operations on the constant i are translated into
VM operations on the segment entry constant i
• This syntactical convention will make sense when we write the compiler.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push constant i
VM code:
push constant i
Assembly psuedo code:
VM Translator
*SP = i, SP++
(no pop constant operation)
Implementation:
Supplies the specified constant
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Memory segments
memory
segments
0
1
2
3
...
Syntax: push/pop segment i
local
argument
this
...
...
...
...
...
...
...
...
...
that
constant
static
pointer
temp
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push/pop static i
memory
segments
0
1
2
3
...
Syntax: push/pop static i
local
argument
this
...
...
...
...
...
...
...
...
...
that
constant
static
pointer
temp
Why do we need a static segment?
When translating high-level code into VM code:
•
high-level operations on static variables are translated into
VM operations on entries of the segment static
•
We now turn to discuss how the static segment is realized on the host platform.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push/pop static i
VM code:
Generated assembly code:
// File Foo.vm
...
...
// D = stack.pop (code omitted)
pop static 5
@Foo.5
...
VM translator
M=D
pop static 2
...
...
// D = stack.pop (code omitted)
The challenge:
static variables should be seen
by all the methods in a program
@Foo.2
M=D
...
Solution:
Store them in some “global space”:
• Have the VM translator translate each VM reference
static i (in file Foo.vm) into an assembly reference Foo.i
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push/pop static i
VM code:
Generated assembly code:
// File Foo.vm
...
...
// D = stack.pop (code omitted)
pop static 5
@Foo.5
...
VM translator
M=D
pop static 2
...
...
// D = stack.pop (code omitted)
The challenge:
static variables should be seen
by all the methods in a program
Hack RAM
@Foo.2
M=D
...
Solution:
Store them in some “global space”:
• Have the VM translator translate each VM reference
static i (in file Foo.vm) into an assembly reference Foo.i
• Following assembly, the Hack assembler will map these
references onto RAM[16], RAM[17], ..., RAM[255]
• Therefore, the entries of the static segment will end up
being mapped onto RAM[16], RAM[17], ..., RAM[255],
in the order in which they appear in the program.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The static segment’s
implementation is different
from that of the previous
segments. There is no
associated ‘pointer’.
Memory segments
memory
segments
0
1
2
3
...
Syntax: push/pop segment i
local
argument
this
...
...
...
...
...
...
...
...
...
that
constant
static
temp
pointer
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push/pop temp i
memory
segments
0
1
2
3
...
Syntax: push/pop temp i
local
argument
this
...
...
...
...
...
...
...
...
...
that
constant
static
temp
pointer
Why do we need the temp segment?
• So far, all the variable kinds that we discussed came from the source code.
• Sometimes, the compiler needs to use some working variables of its own.
(NB: Not to be confused with the implementation’s use of working (temporary)
variables.)
• Our VM provides 8 such variables, stored in a segment named temp.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push/pop temp i
VM code:
push temp i
Hack RAM
pop temp i
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push/pop temp i
VM code:
Assembly psuedo code:
push temp i
addr = 5 + i, *SP = *addr, SP++
VM Translator
Hack RAM
pop temp i
addr = 5 + i, SP--, *addr = *SP
A fixed, 8-place memory segment,
stored in RAM locations 5 to 12
NB: There is no RAM location called
TEMP that stores the base address.
The base address is fixed at 5.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Memory segments
memory
segments
0
1
2
3
...
Syntax: push/pop segment i
local
argument
this
...
...
...
...
...
...
...
...
...
that
constant
static
temp
pointer
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push/pop pointer 0/1
memory
segments
0
1
2
3
...
Syntax: push/pop pointer 0/1
local
argument
this
...
...
...
...
...
...
...
...
...
that
constant
static
temp
pointer
Why do we need the pointer segment?
• We use it for storing the base addresses of the segments this and that
• The need for this will become clear when we’ll write the compiler.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementing push/pop pointer 0/1
VM code:
Assembly psuedo code:
push pointer 0/1
*SP = THIS/THAT, SP++
VM Translator
pop pointer 0/1
SP--, THIS/THAT = *SP
A fixed, 2-place segment:
•
•
accessing pointer 0 should result in accessing THIS
accessing pointer 1 should result in accessing THAT
NB: There is no RAM location called
POINTER. References are mapped to
THIS and THAT depending on the
index used.
Implementation:
Supplies THIS or THAT
// (the base addresses of this and that).
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
VM language
Arithmetic / Logical commands
add
Branching commands
label label
sub
neg
goto label
eq
if-goto label
get
lt
and
or
not
Memory access commands
Function commands
function functionName nVars
call functionName nArgs
return
pop segment i
push segment i
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Review
• We have reviewed the operation of the push and pop
instructions, which are fundamental to all the low-level
operations.
• We have introduced the concept of ‘pointer’: a memory
location holding the address of another location.
• Managing a ‘stack pointer’ (SP) will be crucial to the Hack
implementation of the VM.
• We have seen how implementation of several of the VM’s
segments is supported by dedicated pointers stored in lowaddress RAM locations: LCL, ARG, THIS and THAT.
• The constant, pointer, static and temp segments have
distinctive implementations in the Hack architecture.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Virtual machine: lecture plan
ü The road ahead
• The VM emulator
ü Program compilation
overview
• VM implementation on the
Hack platform
ü VM abstraction:
• The VM translator:
proposed implementation
ü the stack
ü memory segments
ü VM implementation:
• Building the VM translator,
Part I
ü the stack
ü memory segments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM Emulator
Typical uses of the VM emulator:
• Running (compiled) Jack programs
• Experimenting with VM commands
• Observing the VM internals
(stack, memory segments)
• Observing how the VM is realized
on the host platform.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM Emulator
execution
controls
Multi-purpose pane:
• Program output
VM
code
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM Emulator
execution
controls
Multi-purpose pane:
• Program output
• Test script
• Output file
• Compare file
VM
code
stack
memory
segments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Example
BasicTest.vm
...
push constant 10
pop local 0
push constant 21
push constant 22
pop argument 2
pop argument 1
push constant 36
pop this 6
...
VM
code
abstraction
Things to watch for:
(during the code’s
execution)
• Stack state
• Memory segments
states
implementation
How the stack and memory
segments are realized on the
host platform
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Test script
BasicTest.vm
BasicTestVME.tst
...
push constant 10
pop local 0
push constant 21
push constant 22
pop argument 2
pop argument 1
push constant 36
pop this 6
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Test script
There’s no need to
delve into the code
of test scripts
BasicTestVME.tst
BasicTest.vm
load BasicTest.vm,
output-file BasicTest.out,
compare-to BasicTest.cmp,
output-list RAM[256]%D1.6.1 RAM[300]%D1.6.1 ...
...
push constant 10
pop local 0
push constant 21
push constant 22
pop argument 2
pop argument 1
push constant 36
pop this 6
...
BasicTest.out
BasicTest.cmp
|RAM[256]|RAM[300]|RAM[401]|RAM[402]|RAM[3006|RAM[3012|RAM[3015|RAM[11] |
|
472 |
10 |
21 |
22 |
36 |
42 |
45 |
510 |
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Test script
There’s no need to
delve into the code
of test scripts
BasicTestVME.tst
BasicTest.vm
load BasicTest.vm,
output-file BasicTest.out,
compare-to BasicTest.cmp,
output-list RAM[256]%D1.6.1 RAM[300]%D1.6.1 ...
...
push constant 10
pop local 0
push constant 21
push constant 22
pop argument 2
pop argument 1
push constant 36
pop this 6
...
repeat 25 {
vmstep;
}
// BasicTest.vm has 25 instructions
// Outputs some values, as specified by the output-list
// (stack base + selected values from the tested mem. segments)
output;
BasicTest.out
BasicTest.cmp
|RAM[256]|RAM[300]|RAM[401]|RAM[402]|RAM[3006|RAM[3012|RAM[3015|RAM[11] |
|
472 |
10 |
21 |
22 |
36 |
42 |
45 |
510 |
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Test script
There’s no need to
delve into the code
of test scripts
BasicTestVME.tst
BasicTest.vm
load BasicTest.vm,
output-file BasicTest.out,
compare-to BasicTest.cmp,
output-list RAM[256]%D1.6.1 RAM[300]%D1.6.1 ...
...
push constant 10
pop local 0
push constant 21
push constant 22
pop argument 2
pop argument 1
push constant 36
pop this 6
...
repeat 25 {
vmstep;
}
// BasicTest.vm has 25 instructions
// Outputs some values, as specified by the output-list
// (stack base + selected values from the tested mem. segments)
output;
BasicTest.out
if (.out == .cmp )
the test is
successful
else
error
|RAM[256]|RAM[300]|RAM[401]|RAM[402]|RAM[3006|RAM[3012|RAM[3015|RAM[11] |
|
472 |
10 |
21 |
22 |
36 |
42 |
45 |
510 |
BasicTest.cmp
|RAM[256]|RAM[300]|RAM[401]|RAM[402]|RAM[3006|RAM[3012|RAM[3015|RAM[11] |
|
472 |
10 |
21 |
22 |
36 |
42 |
45 |
510 |
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Some missing elements
BasicTest.vm
...
push constant 10
pop local 0
push constant 21
push constant 22
pop argument 2
pop argument 1
push constant 36
pop this 6
...
BasicTestVME.tst
There’s no need to
delve into the code
of test scripts
load BasicTest.vm,
output-file BasicTest.out,
compare-to BasicTest.cmp,
output-list RAM[256]%D1.6.1 RAM[300]%D1.6.1 ...
repeat 25 {
vmstep;
}
// BasicTest.vm has 25 instructions
// Outputs some values, as specified by the output-list
// (stack base + selected values from the tested mem. segments)
output;
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Some missing elements
BasicTest.vm
function Foo.bar
...
push constant 10
pop local 0
push constant 21
push constant 22
pop argument 2
pop argument 1
push constant 36
pop this 6
...
return
BasicTestVME.tst
There’s no need to
delve into the code
of test scripts
load BasicTest.vm,
output-file BasicTest.out,
compare-to BasicTest.cmp,
output-list RAM[256]%D1.6.1 RAM[300]%D1.6.1 ...
set sp 256,
set local 300,
set argument 400,
set this 3000,
set that 3010,
// stack pointer
// base address of the local segment
// base address of the argument segment
// base address of the this segment
// base address of the that segment
repeat 25 {
vmstep;
}
// BasicTest.vm has 25 instructions
// Outputs some values, as specified by the output-list
// (stack base + selected values from the tested mem. segments)
output;
Some missing elements
• function / return “envelope”
Initialization is handled
manually by the supplied
test script
• Initializing the stack and the memory segments on the host RAM
• (both will be added in project 8)
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Recap: the VM Emulator
The VM emulator helps us:
• Run and test high-level programs
• Understand ...
o
the VM abstraction
o
the VM implementation
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Virtual machine: lecture plan
ü The road ahead
ü The VM emulator
ü Program compilation
overview
• VM implementation on the
Hack platform
ü VM abstraction:
• The VM translator:
proposed implementation
ü the stack
ü memory segments
ü VM implementation:
• Building the VM translator,
Part I
ü the stack
ü memory segments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
VM translator
VM code
push constant 2
push local 0
sub
push local 1
push constant 5
add
sub
pop local 2
...
Assembly code
VM translator
Each VM command is
translated into several
assembly commands
// push constant 2
@2
D=A
@SP
A=M
M=D
@SP
M=M+1
// push local 0
...
In order to write a VM translator, we must be familiar with:
Ø
the source language
the target language
Ø
the VM mapping on the target platform.
Ø
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Source: VM language
Arithmetic / Logical commands
add
sub
neg
eq
gt
lt
Branching commands
label label
goto label
if-goto label
Function commands
and
or
function functionName nVars
not
call functionName nArgs
return
Memory access commands
pop segment i
push segment i
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Target: symbolic Hack code
A instruction:
@ value
where value is either a non-negative decimal
constant or a symbol referring to such a constant
sets the A register to value;
q makes M the RAM location whose address is value.
q (M stands for RAM[A])
Semantics:
q
C instruction:
dest = comp ; jump
(dest and jump are optional)
where:
comp =
dest =
jump =
Semantics:
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
null, M, D, MD, A, AM, AD, AMD
q
(M stands for RAM[A])
null, JGT, JEQ, JGE, JLT, JNE, JLE, JMP
q
computes the value of comp and stores the result in dest;
q
if (comp jump 0) is true, jumps to execute the instruction in ROM[A].
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Standard VM mapping on the Hack platform
VM mapping decisions:
• How to map the VM’s data structures using the host hardware platform
• How to express the VM’s commands using the host machine language
Standard mapping:
• Specifies how to do the mapping in an agreed-upon way
• Benefits:
q
Compatibility with other software systems
q
Standard testing.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Standard VM mapping on the Hack platform
Hack RAM
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Standard VM mapping on the Hack platform
Hack RAM
local, argument, this, that:
allocated dynamically to the RAM. The base addresses of these
allocations are kept in the segment pointers LCL, ARG, THIS, THAT
accessing segment i should result in accessing
RAM[*segmentPointer + i]
constant: accessing constant i should result in supplying the constant i
static:
accessing static i within file Foo.vm should result in accessing
the assembly variable Foo.i
temp:
fixed segment, mapped on RAM addresses 5-12.
accessing temp i should result in accessing RAM[5+i]
pointer: fixed segment, mapped on RAM addresses 3-4.
accessing pointer 0 should result in accessing THIS
accessing pointer 1 should result in accessing THAT
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Standard VM mapping on the Hack platform
Hack RAM
In order to realize this mapping, the VM translator should use some
special variables / symbols:
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Standard VM mapping on the Hack platform
Hack RAM
In order to realize this mapping, the VM translator should use some
special variables / symbols:
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Standard VM mapping on the Hack platform
Hack RAM
In order to realize this mapping, the VM translator should use some
special variables / symbols:
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Standard VM mapping on the Hack platform
Hack RAM
In order to realize this mapping, the VM translator should use some
special variables / symbols:
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Standard VM mapping on the Hack platform
Hack RAM
In order to realize this mapping, the VM translator should use some
special variables / symbols:
Implementation note:
The standard mapping will be extended in project 8,
when we’ll complete the VM translator’s implementation.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Virtual machine: lecture plan
ü The road ahead
ü The VM emulator
ü Program compilation
overview
ü VM implementation on the
Hack platform
ü VM abstraction:
• The VM translator:
proposed implementation
ü the stack
ü memory segments
ü VM implementation:
• Building the VM translator,
Part I
ü the stack
ü memory segments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code ( fileName.vm)
Generated assembly code ( fileName.asm)
...
push constant 17
push local 2
add
VM
translator
pop argument 1
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code ( fileName.vm)
Generated assembly code ( fileName.asm)
...
...
push constant 17
push local 2
add
VM
translator
// push constant 17
@17
D=A
... additional assembly commands that complete the
implementation of push constant 17
pop argument 1
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code ( fileName.vm)
Generated assembly code ( fileName.asm)
...
...
push constant 17
push local 2
add
VM
translator
// push constant 17
@17
D=A
... additional assembly commands that complete the
implementation of push constant 17
pop argument 1
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code ( fileName.vm)
Generated assembly code ( fileName.asm)
...
...
push constant 17
push local 2
add
pop argument 1
VM
translator
// push constant 17
@17
D=A
... additional assembly commands that complete the
implementation of push constant 17
// push local 2
... generated assembly code that implements push local 2
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code ( fileName.vm)
Generated assembly code ( fileName.asm)
...
...
push constant 17
push local 2
add
pop argument 1
VM
translator
// push constant 17
@17
D=A
... additional assembly commands that complete the
implementation of push constant 17
// push local 2
... generated assembly code that implements push local 2
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code ( fileName.vm)
Generated assembly code ( fileName.asm)
...
...
push constant 17
push local 2
add
pop argument 1
...
VM
translator
// push constant 17
@17
D=A
... additional assembly commands that complete the
implementation of push constant 17
// push local 2
... generated assembly code that implements push local 2
// add
... generated assembly code that implements add
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code ( fileName.vm)
Generated assembly code ( fileName.asm)
...
...
push constant 17
push local 2
add
pop argument 1
...
VM
translator
// push constant 17
@17
D=A
... additional assembly commands that complete the
implementation of push constant 17
// push local 2
... generated assembly code that implements push local 2
// add
... generated assembly code that implements add
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code ( fileName.vm)
Generated assembly code ( fileName.asm)
...
...
push constant 17
push local 2
add
pop argument 1
...
VM
translator
// push constant 17
@17
D=A
... additional assembly commands that complete the
implementation of push constant 17
// push local 2
... generated assembly code that implements push local 2
// add
... generated assembly code that implements add
// pop argument 1
... generated assembly code that implements push argument 1
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM translator: usage
%
% java VMTranslator myProg.vm
%
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Implementation
Proposed design:
• Parser:
parses each VM command into its lexical elements
• CodeWriter: writes the assembly code that implements the parsed command
• Main:
drives the process (VMTranslator)
Main (VMTranslator)
Input:
fileName.vm
Output:
fileName.asm
Main logic:
• Constructs a Parser to handle the input file
• Constructs a CodeWriter to handle the output file
• Marches through the input file, parsing each line and generating code from it
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Parser
•
Handles the parsing of a single .vm file
•
Reads a VM command, parses the command into its lexical
components, and provides convenient access to these components
•
Ignores all white space and comments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Parser
•
Handles the parsing of a single .vm file
•
Reads a VM command, parses the command into its lexical
components, and provides convenient access to these components
•
Ignores all white space and comments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Parser
•
Handles the parsing of a single .vm file
•
Reads a VM command, parses the command into its lexical
components, and provides convenient access to these components
•
Ignores all white space and comments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Parser
•
Handles the parsing of a single .vm file
•
Reads a VM command, parses the command into its lexical
components, and provides convenient access to these components
•
Ignores all white space and comments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
CodeWriter
Generates assembly code from the parsed VM command:
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
CodeWriter
Generates assembly code from the parsed VM command:
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
CodeWriter
Generates assembly code from the parsed VM command:
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
CodeWriter
Generates assembly code from the parsed VM command:
More routines will be added to this module in Project 8,
when we complete the implementation of the VM translator.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The big picture
VM language:
Arithmetic / Logical commands:
add
sub
neg
eq
gt
lt
and
or
not
Branching commands:
label label
goto label
if-goto label
Function commands:
function functionName nVars
call functionName nArgs
return
Memory access commands:
pop segment i
push segment i
Project 7
Project 8
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Virtual machine: lecture plan
ü The road ahead
ü The VM emulator
ü Program compilation
overview
ü VM implementation on the
Hack platform
ü VM abstraction:
ü The VM translator:
proposed implementation
ü the stack
ü memory segments
ü VM implementation:
• Building the VM translator,
Part I
ü the stack
ü memory segments
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The big picture
human
thought
write a
program
abstraction
p9
high-level
language
compiler
abstraction
p10
OS
p12
p11
VM
translator
VM code
abstraction
p7
p8
machine
language
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The big picture
human
thought
write a
program
abstraction
p9
high-level
language
compiler
abstraction
p10
OS
p12
p11
VM
translator
VM code
abstraction
p7
p8
machine
language
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
The VM language
VM language:
Arithmetic / Logical commands:
add
sub
neg
eq
gt
lt
and
or
not
Branching commands:
label label
goto label
if-goto label
Function commands:
function functionName nVars
call functionName nArgs
return
Memory access commands:
pop segment i
push segment i
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Project 7
Objective: build a basic VM translator that handles a subset of the VM
language: stack arithmetic and memory access (push/pop) commands
VM language:
Arithmetic / Logical commands:
add
sub
neg
eq
gt
lt
and
or
not
Branching commands:
label label
goto label
if-goto label
Function commands:
function functionName nVars
call functionName nArgs
return
Memory access commands:
pop segment i
push segment i
Project 7
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Project 7
Objective: build a basic VM translator that handles a subset of the VM
language: stack arithmetic and memory access (push/pop) commands
fileName.vm
fileName.asm
...
push constant 17
push local 2
add
pop argument 1
VM
translator
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Project 7
Objective: build a basic VM translator that handles a subset of the VM
language: stack arithmetic and memory access (push/pop) commands
fileName.vm
fileName.asm
...
...
push constant 17
// push constant 17
@17
D=A
...
// push local 2
... generated assembly code that implements push local 2
push local 2
add
pop argument 1
...
VM
translator
// add
... generated assembly code that implements add
// pop argument 1
... generated assembly code that implements push argument 1
...
To test the translation:
Run the generated code on the target platform
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Project 7: testing
human
thought
write a
program
abstraction
p9
high-level
language
compiler
abstraction
p10
OS
p12
p11
VM
translator
VM code
abstraction
p7
p8
machine
language
p6
Testing option 1:
• Translate the generated assembly code into machine language,
• Run the binary code of the Hack computer
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Project 7: testing
human
thought
write a
program
abstraction
p9
high-level
language
compiler
abstraction
p10
OS
p12
p11
VM
translator
VM code
abstraction
p7
p8
machine
language
Testing option 2 (simpler):
• Run the generated assembly code on the CPU emulator.
CPU
or
emulat
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Development Plan
Objective: build a basic VM translator that handles the VM language
stack arithmetic and memory access (push/pop) commands
Contract
• Write a VM-to-Hack translator,
conforming to the Standard VM-onHack Mapping
• Use your VM translator to translate
and test the supplied .vm programs,
yielding corresponding .asm programs
Test programs
q
q
SimpleAdd
StackTest
q
BasicTest
PointerTest
q
StaticTest
q
q
q
q
q
BasicTest.vm
BasicTest.tst
BasicTest.cmp
BasicTestVME.tst
BasicTest.vm (example)
...
push constant 510
pop temp 6
push local 0
BasicTest.asm
push that 5
add
...
push argument 1// push constant 510
sub
@510
...
D=A
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Development Plan
Objective: build a basic VM translator that handles the VM language
stack arithmetic and memory access (push/pop) commands
Contract
• Write a VM-to-Hack translator,
conforming to the Standard VM-onHack Mapping
• Use your VM translator to translate
and test the supplied .vm programs,
yielding corresponding .asm programs
• When executed on the supplied CPU
emulator, the generated .asm programs
should deliver the same results
mandated by the supplied test scripts
and compare files.
Test programs
q
q
SimpleAdd
StackTest
q
BasicTest
PointerTest
q
StaticTest
q
q
q
q
q
BasicTest.vm
BasicTest.tst
BasicTest.cmp
BasicTestVME.tst
BasicTest.vm (example)
...
push constant 510
pop temp 6
push local 0
BasicTest.asm
push that 5
add
...
push argument 1// push constant 510
sub
@510
...
D=A
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Development Plan
Objective: build a basic VM translator that handles the VM language
stack arithmetic and memory access (push/pop) commands
For each test xxx.vm program:
0. (optional) load xxxVME.tst into the VM
emulator; run the test script and inspect
the program’s operation
1. use your translator to translate xxx.vm;
The result will be a file named xxx.asm
2. inspect the generated code;
If there’s a problem, fix your translator
and go to stage 1
3. Load xxx.tst into the CPU emulator
4. Run the test script, inspect the results
5. If there’s a problem, fix your translator
and go to stage 1.
Test programs
q
q
SimpleAdd
StackTest
q
BasicTest
PointerTest
q
StaticTest
q
q
q
q
q
BasicTest.vm
BasicTest.tst
BasicTest.cmp
BasicTestVME.tst
BasicTest.vm (example)
...
push constant 510
pop temp 6
push local 0
BasicTest.asm
push that 5
add
...
push argument 1// push constant 510
sub
@510
...
D=A
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Tools and resources
Objective: build a basic VM translator that handles the VM language
stack arithmetic and memory access (push/pop) commands
Tools and resources:
• Test programs and compare files: nand2tetris/projects/07
• Experimenting with the test VM programs: the supplied VM emulator
• Translating the test VM programs into assembly: your VM translator
• Testing the resulting assembly code: the supplied CPU emulator
• Programming language for implementing your VM translator: Java, Python, ...
• Tutorials: VM emulator, CPU emulator (nand2tetris web site)
• Reference: chapter 7 in The Elements of Computing Systems
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Some testing issues
Objective: build a basic VM translator that will be extended in project 8
BasicTest.vm
...
push constant 510
pop temp 6
push local 0
push that 5
add
push argument 1
BasicTest.asm
sub
...
push this 6
// push constant 510
...
@510
D=A
...
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Some testing issues
Objective: build a basic VM translator that will be extended in project 8
BasicTest.tst (for CPU emulator)
BasicTest.vm
function Foo.bar
...
push constant 510
pop temp 6
push local 0
push that 5
add
push argument 1
BasicTest.asm
sub
...
push this 6
// push constant 510
...
return
@510
D=A
...
Missing elements (in project 7)
• function / return “envelope”
• Mapping of the stack and the memory segments
on the host RAM
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Some testing issues
Objective: build a basic VM translator that will be extended in project 8
BasicTest.tst (for CPU emulator)
BasicTest.vm
load BasicTest.asm,
function Foo.bar
...
push constant 510
pop temp 6
push local 0
push that 5
There’s no need
to delve into the
test’s code
add
push argument 1
BasicTest.asm
sub
...
push this 6
// push constant 510
...
return
@510
D=A
...
output-file BasicTest.out,
compare-to BasicTest.cmp,
output-list RAM[256] RAM[300] ...
set RAM[0] 256,
// base of stack
set RAM[1] 300,
set RAM[2] 400,
set RAM[3] 3000,
set RAM[4] 3010,
// base of local
// base of argument
// base of this
// base of that
repeat 600 {
ticktock;
}
output;
Missing elements (in project 7)
• function / return “envelope”
• Mapping of the stack and the memory segments
on the host RAM
The stack and segment base
addresses are handled by the
supplied test scripts, using fixed
addresses
(In project 8 the mappings will
be handled dynamically, by the
VM implementation)
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Recap
VM language:
Arithmetic / Logical commands:
add
sub
neg
eq
gt
lt
and
or
not
Branching commands:
label label
goto label
if-goto label
Function commands:
function functionName nVars
call functionName nArgs
return
Memory access commands:
push segment i
pop segment i
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Recap
Objective: build a basic VM translator that handles the VM language
stack arithmetic and memory access (push/pop) commands
VM language:
Arithmetic / Logical commands:
add
sub
neg
eq
gt
lt
and
or
not
Branching commands:
label label
goto label
if-goto label
Function commands:
function functionName nVars
call functionName nArgs
return
Memory access commands:
push segment i
pop segment i
Project 7
Project 8
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
Perspective
(A subset of historical notes and additional issues)
• History of VMs and two-tier compilation:
q
p-code
q
Sun
q
Cellphones
• How close is our VM to Java’s JVM?
• Efficiency and optimization
• Different VM implementations:
q
q
q
Stack machine
Register machine
Other approaches.
Nand to Tetris / www.nand2tetris.org / Chapter 7 / Copyright © Noam Nisan and Shimon Schocken
CO557: The Virtual Machine, Part II
David Barnes
Chapter 8
Design of the VM
These slides support chapter 8 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Virtual machine
Overview
• Program control
Branching
• Abstraction
• Implementation
Functions
Implementing function call-and-return:
• Implementation overview
• Run-time simulation
• Detailed implementation
VM implementation on the Hack platform:
• Standard mapping
• Abstraction
• VM translator:
proposed implementation
• Implementation
• Project 8 overview
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Program control
x = -b + b 2 - 4 × a × c
This is what we would like to be able to write.
High-level expression:
x = −b + sqrt(power(b,2) – 4 * a * c)
Or:
x = −b + sqrt(disc(a,b,c))
Functions:
•
sqrt, power, and disc are abstractions
•
Functions and class definitions allow us to extend the basic language.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Program control
High-level code
VM code (pseudo)
if !(a==0)
x=(−b+sqrt(disc(a,b,c))/(2*a);
else
x=-c/b;
// code continues
compiler
push a
push 0
eq
not
if-goto A_NEQ_ZERO
// We get here if a==0
push c
neg
push b
call div
pop x
goto CONTINUE
label A_NEQ_ZERO
// We get here if !(a==0)
push b
neg
push a
push b
push c
call disc
call sqrt
add
push 2
push a
call mult
call div
pop x
label CONTINUE
// code continues
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
NB: Remember that the VM
doesn’t have a != operation,
but it’s effect can be realised by
combining == with boolean
negation.
NB: Notice that the order
of the code for the true
and false destinations has
been swapped.
Program control
High-level code
VM code (pseudo)
if !(a==0)
x=(−b+sqrt(disc(a,b,c))/(2*a);
else
x=-c/b;
// code continues
compiler
push a
push 0
eq
not
if-goto A_NEQ_ZERO
// We get here if a==0
push c
neg
push b
call div
pop x
goto CONTINUE
label A_NEQ_ZERO
// We get here if !(a==0)
push b
neg
push a
push b
push c
call disc
call sqrt
add
push 2
push a
call mult
call div
pop x
label CONTINUE
// code continues
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Program control
VM code (pseudo)
VM branching commands:
• goto label
• if-goto label
• label label
VM function commands:
• call function
• function function
• return
Challenges:
• Understanding what the
commands do (abstraction)
• Realizing the commands on the
host platform (implementation)
push a
push 0
eq
not
if-goto A_NEQ_ZERO
// We get here if a==0
push c
neg
push b
call div
pop x
goto CONTINUE
label A_NEQ_ZERO
// We get here if !(a==0)
push b
neg
push a
push b
push c
call disc
call sqrt
add
push 2
push a
call mult
call div
pop x
label CONTINUE
// code continues
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Program control
• Why was the order of the code swapped when translating
the if statement?
if !(a==0)
x=(−b+sqrt(disc(a,b,c))/(2*a);
• In the more ‘natural’ translation
else
there will always be a jump.
x=-c/b;
// code continues
• An alternative would be to
retain the natural order but
‘invert’ the boolean condition.
push a
push 0
eq
if-goto A_EQ_ZERO
// We get here if !(a==0)
push b
…
goto CONTINUE
label A_EQ_ZERO
// We get here if a==0
…
label CONTINUE
// code continues
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
push a
push 0
eq
not
if-goto A_NEQ_ZERO
goto A_EQ_ZERO
label A_NEQ_ZERO
// We get here if !(a==0)
push b
neg
push a
push b
push c
call disc
call sqrt
add
push 2
push a
call mult
call div
pop x
goto CONTINUE
label A_EQ_ZERO
// We get here if a==0
push c
neg
push b
call div
pop x
label CONTINUE
// code continues
To be covered …
Understanding how programs are executed:
• Branching
• Function call-and-return
Related implementation issues:
• Stack processing
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Branching
command
command
command
label a
Branching:
command
command
• Unconditional
command
if condition goto b
• Conditional
command
command
command
command
command
label b
command
command
command
command
command
if condition goto c
command
command
command
label c
command
command
command
goto a
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Branching
High-level program
// Returns x * y
int mult(int x, int y) {
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Branching
High-level program
// Returns x * y
int mult(int x, int y) {
int sum = 0;
int n = 1;
// sum = sum + x, y times
while !(n > y) {
sum += x;
n++;
}
return sum;
}
Notice, again, that the more
natural n <= y is being
represented as !(n > y)
because the VM only has gt, lt
and eq operations.
Let’s focus on
the while logic
In practice, we could write the
code more naturally at the source
level and the compiler would take
care of the mapping to
accommodate the VM definition.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Branching
High-level program
// Returns x * y
int mult(int x, int y) {
int sum = 0;
int n = 1;
// sum = sum + x, y times
while !(n > y) {
sum += x;
n++;
}
return sum;
}
compiler
Pseudo VM code
function mult(x,y)
push 0
pop sum
push 1
pop n
label WHILE_LOOP
push n
push y
gt
if-goto ENDLOOP
push sum
push x
add
pop sum
push n
push 1
add
pop n
goto WHILE_LOOP
label ENDLOOP
push sum
return
Notice, again, that the more
natural n <= y is being
represented as !(n > y)
because the VM only has gt, lt
and eq operations.
In practice, we could write the
code more naturally at the source
level and the compiler would take
care of the mapping to
accommodate the VM definition.
Notice the inversion of the logic,
as suggested previously.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Branching
High-level program
// Returns x * y
int mult(int x, int y) {
int sum = 0;
int n = 1;
// sum = sum + x, y times
while !(n > y) {
sum += x;
n++;
}
return sum;
}
compiler
Pseudo VM code
function mult(x,y)
push 0
pop sum
push 1
pop n
label WHILE_LOOP
push n
push y
gt
if-goto ENDLOOP
push sum
push x
add
pop sum
push n
push 1
add
pop n
goto WHILE_LOOP
label ENDLOOP
push sum
return
Unconditional branching:
goto label
Jumps to execute the
command just after label.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Branching
High-level program
// Returns x * y
int mult(int x, int y) {
int sum = 0;
int n = 1;
// sum = sum + x, y times
while !(n > y) {
sum += x;
n++;
}
return sum;
}
compiler
Pseudo VM code
function mult(x,y)
push 0
pop sum
push 1
pop n
label LOOP
push n
push y
gt
if-goto ENDLOOP
push sum
push x
add
pop sum
push n
push 1
add
pop n
goto WHILE_LOOP
label ENDLOOP
push sum
return
Conditional branching:
if-goto label
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Branching
High-level program
// Returns x * y
int mult(int x, int y) {
int sum = 0;
int n = 1;
// sum = sum + x, y times
while !(n > y) {
sum += x;
n++;
}
return sum;
}
compiler
Pseudo VM code
function mult(x,y)
push 0
pop sum
push 1
pop n
label LOOP
push n
push y
gt
if-goto ENDLOOP
push sum
push x
add
pop sum
push n
push 1
add
pop n
goto WHILE_LOOP
label ENDLOOP
push sum
return
Conditional branching:
if-goto label
VM logic:
1. cond = pop;
2. if cond jump to execute the
command just after label.
(The relational operations push
their result to the stack.)
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Branching
Recap: VM branching commands:
• goto label
// jump to execute the command just after label
• if-goto label
// cond = pop;
// if cond jump to execute the command just after label
• label label
// label declaration command
Implementation (VM translation):
Translate each branching command into assembly instructions that effect
the specified operation on the host machine
Simple implementation:
the assembly language has similar branching commands.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
VM language
Arithmetic / Logical commands
Branching commands
add
label label
sub
goto label
neg
eq
gt
lt
if-goto label
Function commands
and
function functionName nVars
or
call functionName nArgs
not
return
Memory segment commands
pop segment i
push segment i
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Functions
High-level programming languages can be extended using:
• Subroutines
• Functions
• Procedures
• Methods
‘functions’
in VM
terminology
• Etc.
(Different names
for the same underlying concept.)
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Functions in the VM language
High-level program
Pseudo VM code
...
...
sqrt(x – 17 + x * 5)
...
compiler
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Functions in the VM language
High-level program
...
sqrt(x – 17 + x * 5)
...
compiler
Pseudo VM code
...
push x
push 17
sub
push x
push 5
call Math.mult
add
No ‘multiply’ operation in the VM.
call Math.sqrt
...
• The VM language features:
q
primitive operations (fixed): add, sub, ...
q
abstract operations (extensible): mult, sqrt, ...
Programming style:
q
Applying a primitive operator or calling a function
have the same look-and-feel within the VM code.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Functions in the VM language: defining
High-level program
// Returns x * y
int mult(int x, int y) {
int sum = 0;
int n = 1;
// sum = sum + x, y times
while !(n > y) {
sum += x;
n++;
}
return sum;
}
compiler
Pseudo VM code
function mult(x,y)
push 0
pop sum
push 1
pop n
label LOOP
push n
push y
gt
if-goto END
push sum
push x
add
pop sum
push n
push 1
add
pop n
goto LOOP
label END
push sum
return
Final VM code
function mult 2
// 2 local vars.
push constant 0 // sum=0
pop local 0
push constant 1 // n=1
pop local 1
label LOOP
push local 1
// if !(n>y)
push argument 1 // goto END
gt
if-goto END
push local 0
// sum+=x
push argument 0
add
pop local 0
push local 1
// n++
push constant 1
add
pop local 1
goto LOOP
label END
push local 0
// return sum
return
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Constants, locals and
arguments mapped to
distinct segments.
Functions in the VM language: executing (stack view)
// Computes 3 +5 * 8
0 function main 0
1
push constant 3
2
push constant 8
3
push constant 5
4
call mult 2
5
add
6
return
caller
// Computes the product of two given arguments
0 function mult 2
1
push constant 0
2
pop local 0
(same code as previous
3
push constant 1
slide, with line numbers,
4
pop local 1
for easy reference)
5 label LOOP
6
push local 1
7
push argument 1
//... computes the product into local 0
19 label END
20
push local 0
callee
21
return
main view:
after line 3
is executed:
after line 4
is executed:
Now from the view of mult.
after line 5
is executed:
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Functions in the VM language: executing (stack and segments)
// Computes 3 +5 * 8
0 function main 0
1
push constant 3
2
push constant 8
3
push constant 5
4
call mult 2
5
add
6
return
caller
// Computes the product of two given arguments
0 function mult 2
1
push constant 0
2
pop local 0
3
push constant 1
4
pop local 1
5 label LOOP
6
push local 1
7
push argument 1
//... computes the product into local 0
19 label END
20
push local 0
callee
21
return
main view:
after line 3
is executed:
mult view:
after line 0
is executed:
after line 4
is executed:
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Conceptually, each
function has its own stack
and separate argument and
local areas.
Practically, everything is
mapped to a contiguous
area of the Hack machine’s
RAM.
Functions in the VM language: executing
// Computes the product of two given arguments
0 function mult 2
1
push constant 0
2
pop local 0
(same code as previous
3
push constant 1
slide, with line numbers,
4
pop local 1
for easy reference)
5 label LOOP
6
push local 1
7
push argument 1
//... computes the product into local 0
19 label END
20
push local 0
callee
21
return
// Computes 3 +5 * 8
0 function main 0
1
push constant 3
2
push constant 8
3
push constant 5
4
call mult 2
5
add
6
return
caller
main view:
mult view:
after line 0
is executed:
after line 3
is executed:
after line 4
is executed:
re
tu
rn
after line 7
is executed:
after line 20
is executed:
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Functions in the VM language: executing
// Computes 3 +5 * 8
0 function main 0
1
push constant 3
2
push constant 8
3
push constant 5
4
call mult 2
5
add
6
return
caller
// Computes the product of two given arguments
0 function mult 2
1
push constant 0
2
pop local 0
3
push constant 1
4
pop local 1
5 label LOOP
6
push local 1
7
push argument 1
//... computes the product into local 0
19 label END
20
push local 0
callee
22
return
main view:
after line 3
is executed:
after line 4
is executed:
after line 5
is executed:
mult view:
after line 0
is executed:
after line 7
is executed:
after line 20
is executed:
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Functions in the VM language: implementation
// Computes 3 +5 * 8
function main 0
push constant 3
push constant 8
push constant 5
call mult 2
add
return
caller
// Computes the product of two given arguments
function mult 2
push constant 0
pop local 0
push constant 1
pop local 1
label LOOP
push local 1
push argument 1
//... computes the product into local 0
label END
push local 0
callee
return
Implementation
How to orchestrate the processes just described?
We can write low-level code that manages the parameter passing, the saving and
re-instating of function states, etc.
This task can be realized by writing code that...
• Handles the VM command call
• Handles the VM command function
• Handles the VM command return.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Functions in the VM language: implementation
// Computes 3 +5 * 8
function main 0
push constant 3
push constant 8
push constant 5
call mult 2
add
return
caller
// Computes the product of two given arguments
function mult 2
push constant 0
pop local 0
push constant 1
pop local 1
label LOOP
push local 1
push argument 1
//... computes the product into local 0
label END
push local 0
callee
return
Handling call:
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Functions in the VM language: implementation
// Computes 3 +5 * 8
function main 0
push constant 3
push constant 8
push constant 5
call mult 2
add
return
caller
// Computes the product of two given arguments
function mult 2
push constant 0
pop local 0
push constant 1
pop local 1
label LOOP
push local 1
push argument 1
//... computes the product into local 0
label END
push local 0
callee
return
Handling call:
•
Determine the return address within the caller’s code;
•
Save the caller’s return address, stack and memory segments;
•
Pass parameters from the caller to the callee;
•
Jump to execute the callee.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Conceptually.
Practically, only a few ‘pointers’
need to be saved.
Functions in the VM language: implementation
// Computes 3 +5 * 8
function main 0
push constant 3
push constant 8
push constant 5
call mult 2
add
return
caller
// Computes the product of two given arguments
function mult 2
push constant 0
pop local 0
push constant 1
pop local 1
label LOOP
push local 1
push argument 1
//... computes the product into local 0
label END
push local 0
callee
return
Handling function:
•
Initialize the local variables of the callee;
•
Handle some other simple initializations (later).
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Functions in the VM language: implementation
// Computes 3 +5 * 8
function main 0
push constant 3
push constant 8
push constant 5
call mult 2
add
return
caller
// Computes the product of two given arguments
function mult 2
push constant 0
pop local 0
push constant 1
pop local 1
label LOOP
push local 1
push argument 1
//... computes the product into local 0
label END
push local 0
callee
return
Handling return:
•
(a function always ends by pushing a return value on the stack)
•
Return the return value to the caller;
•
Recycle the memory resources used by the callee;
•
Reinstate the caller’s stack and memory segments;
•
Jump to the return address in the caller’s code.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Review
• We have covered basic program flow control commands:
label, goto, if-goto.
• We have looked at the way in which translation of boolean
conditions often involves manipulations such as code
movement or condition inversion, for the sake of efficiency.
• We have looked at the mechanisms of function definition,
call and return.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
CO557: The Virtual Machine, Part II
David Barnes
Chapter 8
Implementation of
function call and return
These slides support chapter 8 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function execution
• A computer program typically consists of many functions
• At any given point of time, only a few functions are executing
• Calling chain:
foo > bar > sqrt > ...
For each function in the calling
chain during run-time, we must
maintain the function’s state
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The function’s state
memory
segments
0
1
2
3
...
...
...
...
...
During run-time:
• Each function uses a working stack + memory segments
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The function’s state
memory
segments
0
1
2
3
...
...
...
...
...
During run-time:
• Each function uses a working stack + memory segments
• The working stack and some of the segments should be:
q
Created when the function starts running,
q
Maintained as long as the function is executing,
q
Recycled when the function returns.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The function’s state
function mult 2
function main 0
push constant 0
pop local 0
...
label LOOP
push local 1
push constant 3
push constant 8
push constant 5
call mult 2
add
return
caller
//... computes the product
label END
push local 0
callee
return
Challenge:
• Maintain the states of all the functions up the calling chain
• Can be done by using a single global stack.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: abstraction
Example: computing mult(17,212)
Caller’s stack (before)
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: abstraction
Example: computing mult(17,212)
Caller’s stack (before)
17
212
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: abstraction
Example: computing mult(17,212)
Caller’s stack (after)
Caller’s stack (before)
call mult 2
17
212
3604
sp
sp
Net effect:
The function’s arguments were replaced by the function’s value.
In effect, the called function ‘consumes’ its arguments and leaves
behind the result it has calculated.
The arguments and return value are the only way in which caller
and callee ‘communicate’.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The function is running,
doing something
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The function prepares
to call another function:
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The function prepares
to call another function:
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The function says:
call foo nArgs
nArgs
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The function says:
call foo nArgs
VM implementation (handling call):
nArgs
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The function says:
call foo nArgs
VM implementation (handling call):
1. Saves the caller’s frame
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
A function’s ‘frame’ is its
execution context: local variables,
its own arguments, etc.
Function call and return: implementation
The function says:
call foo nArgs
VM implementation (handling call):
1. Saves the caller’s frame
A function’s ‘frame’ is its
execution context: local variables,
its own arguments, etc.
Note that SP is not saved. We will
see why later.
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The function says:
call foo nArgs
VM implementation (handling call):
1. Saves the caller’s frame
2. Sets ARG
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The function says:
call foo nArgs
VM implementation (handling call):
1. Saves the caller’s frame
2. Sets ARG
3. Jumps to execute foo
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function is entered:
function foo nVars
VM implementation (handling call):
1. Saves the caller’s frame
2. Sets ARG
3. Jumps to execute foo
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function is entered:
function foo nVars
VM implementation (handling call):
1. Saves the caller’s frame
2. Sets ARG
3. Jumps to execute foo
VM implementation (handling function):
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function is entered:
function foo nVars
VM implementation (handling call):
1. Saves the caller’s frame
2. Sets ARG
3. Jumps to execute foo
VM implementation (handling function):
• Sets up the local segment
of the called function
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function is entered:
function foo nVars
VM implementation (handling call):
1. Saves the caller’s frame
2. Sets ARG
3. Jumps to execute foo
VM implementation (handling function):
• Sets up the local segment
of the called function
nVars
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function is entered:
function foo nVars
VM implementation (handling call):
1. Saves the caller’s frame
2. Sets ARG
3. Jumps to execute foo
VM implementation (handling function):
• Sets up the local segment
of the called function
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function is running,
doing something
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function is running,
doing something
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function prepares to return:
it pushes a return value
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function prepares to return:
it pushes a return value
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function says:
return
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function says:
return
VM implementation (handling call):
1. Saves the caller’s frame
2. Sets ARG
3. Jumps to execute foo
VM implementation (handling function):
• Sets up the local segment
of the called function
VM implementation (handling return):
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function says:
return
VM implementation (handling call):
1. Saves the caller’s frame
returned value
2. Sets ARG
3. Jumps to execute foo
VM implementation (handling function):
• Sets up the local segment
of the called function
VM implementation (handling return):
1. Copies the return value onto argument 0
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function says:
return
VM implementation (handling call):
1. Saves the caller’s frame
returned value
2. Sets ARG
3. Jumps to execute foo
VM implementation (handling function):
• Sets up the local segment
of the called function
VM implementation (handling return):
1. Copies the return value onto argument 0
2. Sets SP for the caller
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
This is why SP was not saved as
part of the caller’s frame.
Function call and return: implementation
The called function says:
return
VM implementation (handling call):
1. Saves the caller’s frame
sp
returned value
2. Sets ARG
3. Jumps to execute foo
VM implementation (handling function):
• Sets up the local segment
of the called function
VM implementation (handling return):
1. Copies the return value onto argument 0
2. Sets SP for the caller
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
This is why SP was not saved as
part of the caller’s frame.
Function call and return: implementation
The called function says:
return
VM implementation (handling call):
1. Saves the caller’s frame
sp
returned value
2. Sets ARG
3. Jumps to execute foo
VM implementation (handling function):
• Sets up the local segment
of the called function
VM implementation (handling return):
1. Copies the return value onto argument 0
2. Sets SP for the caller
3. Restores the segment pointers of the caller
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function says:
return
VM implementation (handling call):
1. Saves the caller’s frame
sp
returned value
2. Sets ARG
3. Jumps to execute foo
VM implementation (handling function):
• Sets up the local segment
of the called function
VM implementation (handling return):
1. Copies the return value onto argument 0
2. Sets SP for the caller
3. Restores the segment pointers of the caller
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The called function says:
return
VM implementation (handling call):
1. Saves the caller’s frame
sp
returned value
2. Sets ARG
3. Jumps to execute foo
VM implementation (handling function):
• Sets up the local segment
of the called function
VM implementation (handling return):
1. Copies the return value onto argument 0
2. Sets SP for the caller
3. Restores the segment pointers of the caller
4. Jumps to the return address within the caller’s code
5. (note that the stack space between old and new sp is
recycled)
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return: implementation
The caller
resumes its execution
VM implementation (handling call):
1. Saves the caller’s frame
sp
returned value
2. Sets ARG
3. Jumps to execute foo
VM implementation (handling function):
• Sets up the local segment
of the called function
VM implementation (handling return):
1. Copies the return value onto argument 0
2. Sets SP for the caller
3. Restores the segment pointers of the caller
4. Jumps to the return address within the caller’s code
5. (note that the stack space between old and new sp is
recycled)
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The global stack
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The global stack
global stack
states of other functions
up the calling chain
(possibly many) similar blocks, one
for each function up the calling chain
“block”
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Review: function call and return
The caller says:
call foo nArgs
The caller resumes
its execution
Abstraction:
sp
return value of foo
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Review: function call and return
The caller says:
The caller resumes
its execution
Implementation:
call foo nArgs
sp
returned value
sp
return value of foo
sp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Virtual machine: lecture plan
Overview
• Program control
Branching
• Abstraction
• Implementation
Functions
Implementing function call-and-return:
• Implementation overview
• Run-time simulation
• Detailed implementation
VM implementation on the Hack platform:
• Standard mapping
• Abstraction
• VM translator:
proposed implementation
• Implementation
• Project 8 overview
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Example: factorial
High-level program
// Tests the factorial function
int main() {
return factorial(3);
}
// Returns n!
int factorial(int n) {
if (n==1)
return 1;
else
return n * factorial(n-1);
}
compiler
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Example: factorial
High-level program
// Tests the factorial function
int main() {
return factorial(3);
}
Pseudo VM code
function main
push 3
call factorial
return
// Returns n!
int factorial(int n) {
if (n==1)
return 1;
else
return n * factorial(n-1);
}
compiler
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Example: factorial
High-level program
// Tests the factorial function
int main() {
return factorial(3);
}
// Returns n!
int factorial(int n) {
if (n==1)
return 1;
else
return n * factorial(n-1);
}
compiler
Pseudo VM code
function main
push 3
call factorial
return
function factorial(n)
push n
push 1
eq
if-goto BASECASE
push n
push n
push 1
sub
call factorial
call mult
return
label BASECASE
push 1
return
function mult(a,b)
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Example: factorial
High-level program
// Tests the factorial function
int main() {
return factorial(3);
}
// Returns n!
int factorial(int n) {
if (n==1)
return 1;
else
return n * factorial(n-1);
}
compiler
Pseudo VM code
VM program
function main
push 3
call factorial
return
function main 0
push constant 3
call factorial 1
return
function factorial(n)
push n
push 1
eq
if-goto BASECASE
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push n
push n
push 1
sub
call factorial
call mult
return
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push 1
return
label BASECASE
push constant 1
return
function mult(a,b)
// Code omitted
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
VM program
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
impact on the
global stack
not shown
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
impact on the
global stack
not shown
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
impact on the
global stack
not shown
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
get the
return address
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
handle the
return value
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
impact on the global stack
not shown
(except for end result)
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
get return
address
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
handle the
return value
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
impact on the global stack
not shown
(except for end result)
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
6
impact on the global stack
not shown
(except for end result)
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
6
get return
address
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
6
6
handle the
return value
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
6
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Run-time example
function main 0
push constant 3
call factorial 1
return
6
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Recap
function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
6
The caller (main function) wanted to compute 3!
q
it pushed 3, called factorial, and got 6
q
from the caller’s view, nothing exciting happenned...
abstraction
implementation
function mult 2
// Code omitted
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Virtual machine: lecture plan
Overview
• Program control
Branching
• Abstraction
• Implementation
Functions
Implementing function call-and-return:
• Implementation overview
• Run-time simulation
• Detailed implementation
VM implementation on the Hack platform:
• Standard mapping
• Abstraction
• VM translator:
proposed implementation
• Implementation
• Project 8 overview
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return
VM code (arbitrary example)
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
caller
callee
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
We focus on the VM function commands:
• call functionName nArgs
• function functionName nVars
• return
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Contract: the caller’s view
VM code
caller
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
• Before calling another function, I must push as
many arguments as the function expects to get
• Next, I invoke the function using
call functionName nArgs
• After the called function returns, the argument
values that I pushed before the call have
disappeared from the stack, and a return value
(that always exists) appears at the top of the stack;
• After the called function returns, all my memory
segments are exactly the same as they were before
the call
• (except that temp is undefined and some values of
my static segment may have changed).
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Contract: the caller’s view
VM code
caller
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
• Before calling another function, I must push as
many arguments as the function expects to get
• Next, I invoke the function using
call functionName nArgs
• After the called function returns, the argument
values that I pushed before the call have
disappeared from the stack, and a return value
(that always exists) appears at the top of the stack;
• After the called function returns, all my memory
segments are exactly the same as they were before
the call
• (except that temp is undefined and some values of
my static segment may have changed).
blue: must be handled by the
VM implementation
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Contract: the callee’s view
VM code
callee
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
• Before I start executing, my argument segment
has been initialized with the argument values
passed by the caller
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
• (memory segments this, that, pointer, and temp
are undefined upon entry)
• My local variables segment has been allocated
and initialized to zeros
• My static segment has been set to the static
segment of the VM file to which I belong
• My stack is empty
• Before returning,
I must push a value onto the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Contract: the callee’s view
VM code
callee
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
• Before I start executing, my argument segment
has been initialized with the argument values
passed by the caller
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
• (memory segments this, that, pointer, and temp
are undefined upon entry)
• My local variables segment has been allocated
and initialized to zeros
• My static segment has been set to the static
segment of the VM file to which I belong
• My stack is empty
• Before returning,
I must push a value onto the stack.
blue: must be handled by
the VM implementation
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM implementation view
VM code
Generated assembly code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM implementation view
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM implementation view
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM implementation view
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
// assembly code that saves the caller’s state on the stack,
// sets up for the function call, and then:
goto Bar.mult
// (in assembly)
(Foo$ret.1)
// created and plugged by the translator
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM implementation view
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
// assembly code that saves the caller’s state on the stack,
// sets up for the function call, and then:
goto Bar.mult
// (in assembly)
(Foo$ret.1)
// created and plugged by the translator
// assembly code that handles neg
...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM implementation view
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
// assembly code that saves the caller’s state on the stack,
// sets up for the function call, and then:
goto Bar.mult
// (in assembly)
(Foo$ret.1)
// created and plugged by the translator
// assembly code that handles neg
...
(Bar.mult)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM implementation view
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
// assembly code that saves the caller’s state on the stack,
// sets up for the function call, and then:
goto Bar.mult
// (in assembly)
(Foo$ret.1)
// created and plugged by the translator
// assembly code that handles neg
...
(Bar.mult)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push local 1
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM implementation view
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
// assembly code that saves the caller’s state on the stack,
// sets up for the function call, and then:
goto Bar.mult
// (in assembly)
(Foo$ret.1)
// created and plugged by the translator
// assembly code that handles neg
...
(Bar.mult)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push local 1
// Assembly code that gets the return address (which happens
// to be Foo$ret.1) off the stack, copies the return value to
// the caller, reinstates the caller’s state, and then:
goto Foo$ret.1
// (in assembly)
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM implementation view
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
We now turn to describe the more
detailed handling of the VM commands:
• call
• function
• return
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
// assembly code that saves the caller’s state on the stack,
// sets up for the function call, and then:
pseudo
code
goto Bar.mult
// (in assembly)
(Foo$ret.1)
// created and plugged by the translator
// assembly code that handles neg
...
(Bar.mult)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push local 1
// Assembly code that gets the return address (which happens
// to be Foo$ret.1) off the stack, copies the return value to
// the caller, reinstates the caller’s state, and then:
goto Foo$ret.1
// (in assembly)
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM implementation view
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
// assembly code that saves the caller’s state on the stack,
// sets up for the function call, and then:
goto Bar.mult
// (in assembly)
(Foo$ret.1)
// created and plugged by the translator
// assembly code that handles neg
...
(Bar.mult)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push local 1
// Assembly code that gets the return address (which happens
// to be Foo$ret.1) off the stack, copies the return value to
// the caller, reinstates the caller’s state, and then:
goto Foo$ret.1
// (in assembly)
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
global stack
states of other functions
up the calling chain
the caller is
running, doing
some work...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
global stack
states of other functions
up the calling chain
nArgs
// Using a translator-generated label
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
global stack
states of other functions
up the calling chain
nArgs
// Using a translator-generated label
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
push ARG
// Saves ARG of the caller
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
push ARG
// Saves ARG of the caller
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
push ARG
// Saves ARG of the caller
push THIS
// Saves THIS of the caller
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
push ARG
// Saves ARG of the caller
push THIS
// Saves THIS of the caller
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
push ARG
// Saves ARG of the caller
push THIS
// Saves THIS of the caller
push THAT
// Saves THAT of the caller
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
push ARG
// Saves ARG of the caller
push THIS
// Saves THIS of the caller
push THAT
// Saves THAT of the caller
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
push ARG
// Saves ARG of the caller
push THIS
// Saves THIS of the caller
push THAT
// Saves THAT of the caller
ARG = SP-5-nArgs
// Repositions ARG
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
push ARG
// Saves ARG of the caller
push THIS
// Saves THIS of the caller
push THAT
// Saves THAT of the caller
ARG = SP-5-nArgs
// Repositions ARG
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
push ARG
// Saves ARG of the caller
push THIS
// Saves THIS of the caller
push THAT
// Saves THAT of the caller
ARG = SP-5-nArgs
// Repositions ARG
LCL = SP
// Repositions LCL
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
push ARG
// Saves ARG of the caller
push THIS
// Saves THIS of the caller
push THAT
// Saves THAT of the caller
ARG = SP-5-nArgs
// Repositions ARG
LCL = SP
// Repositions LCL
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
push ARG
// Saves ARG of the caller
push THIS
// Saves THIS of the caller
push THAT
// Saves THAT of the caller
ARG = SP-5-nArgs
// Repositions ARG
LCL = SP
// Repositions LCL
goto functionName
// Transfers control to the called function
global stack
states of other functions
up the calling chain
nArgs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM command:
call functionName nArgs
(calls a function, informing that nArgs arguments
have been pushed onto the stack)
Assembly code (generated by the translator):
push retAddrLabel
// Using a translator-generated label
push LCL
// Saves LCL of the caller
push ARG
// Saves ARG of the caller
push THIS
// Saves THIS of the caller
push THAT
// Saves THAT of the caller
ARG = SP-5-nArgs
// Repositions ARG
LCL = SP
// Repositions LCL
goto functionName
// Transfers control to the called function
(retAddrLabel)
global stack
states of other functions
up the calling chain
nArgs
// the same translator-generated label
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling call
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
// assembly code that saves the caller’s state on the stack,
// sets up for the function call, and then:
goto Bar.mult
// (in assembly)
(Foo$ret.1)
// created and plugged by the translator
// assembly code that handles neg
...
(Bar.mult)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push local 1
// Assembly code that gets the return address (which happens
// to be Foo$ret.1) off the stack, copies the return value to
// the caller, reinstates the caller’s state, and then:
goto Foo$ret.1
// (in assembly)
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling function
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
// assembly code that saves the caller’s state on the stack,
// sets up for the function call, and then:
goto Bar.mult
// (in assembly)
(Foo$ret.1)
// created and plugged by the translator
// assembly code that handles neg
...
(Bar.mult)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push local 1
// Assembly code that gets the return address (which happens
// to be Foo$ret.1) off the stack, copies the return value to
// the caller, reinstates the caller’s state, and then:
goto Foo$ret.1
// (in assembly)
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling function
VM command:
function functionName nVars
(here starts a function that has nVars local
variables)
global stack
states of other functions
up the calling chain
Assembly code (generated by the translator):
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling function
VM command:
function functionName nVars
(here starts a function that has nVars local
variables)
global stack
states of other functions
up the calling chain
Assembly code (generated by the translator):
(functionName)
// using a translator-generated label
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling function
VM command:
function functionName nVars
(here starts a function that has nVars local
variables)
global stack
states of other functions
up the calling chain
Assembly code (generated by the translator):
(functionName)
// using a translator-generated label
repeat nVars times:
// nVars = number of local variables
push 0
// initializes the local variables to 0
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling function
VM command:
function functionName nVars
(here starts a function that has nVars local
variables)
global stack
states of other functions
up the calling chain
Assembly code (generated by the translator):
(functionName)
// using a translator-generated label
repeat nVars times:
// nVars = number of local variables
push 0
// initializes the local variables to 0
nVars
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling function
VM command:
function functionName nVars
(here starts a function that has nVars local
variables)
global stack
states of other functions
up the calling chain
Assembly code (generated by the translator):
(functionName)
// using a translator-generated label
repeat nVars times:
// nVars = number of local variables
push 0
// initializes the local variables to 0
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling function
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
// assembly code that saves the caller’s state on the stack,
// sets up for the function call, and then:
goto Bar.mult
// (in assembly)
(Foo$ret.1)
// created and plugged by the translator
// assembly code that handles neg
...
(Bar.mult)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push local 1
// Assembly code that gets the return address (which happens
// to be Foo$ret.1) off the stack, copies the return value to
// the caller, reinstates the caller’s state, and then:
goto Foo$ret.1
// (in assembly)
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling function
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Generated assembly code
(Foo.main)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
// assembly code that saves the caller’s state on the stack,
// sets up for the function call, and then:
goto Bar.mult
// (in assembly)
(Foo$ret.1)
// created and plugged by the translator
// assembly code that handles neg
...
(Bar.mult)
// created and plugged by the translator
// assembly code that handles the initialization of the
// function’s execution
...
// assembly code that handles push local 1
// Assembly code that gets the return address (which happens
// to be Foo$ret.1) off the stack, copies the return value to
// the caller, reinstates the caller’s state, and then:
goto Foo$ret.1
// (in assembly)
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling return
global stack
states of other functions
up the calling chain
the callee is
running, doing
some work...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling return
global stack
VM command:
return
states of other functions
up the calling chain
the callee is
running, doing
some work...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling return
global stack
VM command:
return
states of other functions
up the calling chain
return
value
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling return
global stack
VM command:
return
states of other functions
up the calling chain
Assembly code (generated by the translator):
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling return
global stack
VM command:
return
states of other functions
up the calling chain
Assembly code (generated by the translator):
endFrame = LCL
// endframe is a temporary variable
retAddr = *(endFrame – 5) // gets the return address
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling return
global stack
VM command:
return
states of other functions
up the calling chain
Assembly code (generated by the translator):
endFrame = LCL
// endframe is a temporary variable
retAddr = *(endFrame – 5) // gets the return address
*ARG = pop()
// repositions the return value for the caller
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling return
global stack
VM command:
return
states of other functions
up the calling chain
Assembly code (generated by the translator):
return value
endFrame = LCL
// endframe is a temporary variable
retAddr = *(endFrame – 5) // gets the return address
*ARG = pop()
// repositions the return value for the caller
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling return
global stack
VM command:
return
states of other functions
up the calling chain
Assembly code (generated by the translator):
return value
endFrame = LCL
// endframe is a temporary variable
retAddr = *(endFrame – 5) // gets the return address
*ARG = pop()
// repositions the return value for the caller
SP = ARG + 1
// repositions SP of the caller
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling return
global stack
VM command:
return
states of other functions
up the calling chain
Assembly code (generated by the translator):
return value
endFrame = LCL
// endframe is a temporary variable
retAddr = *(endFrame – 5) // gets the return address
*ARG = pop()
// repositions the return value for the caller
SP = ARG + 1
// repositions SP of the caller
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling return
global stack
VM command:
return
states of other functions
up the calling chain
Assembly code (generated by the translator):
return value
endFrame = LCL
// endframe is a temporary variable
retAddr = *(endFrame – 5) // gets the return address
*ARG = pop()
// repositions the return value for the caller
SP = ARG + 1
// repositions SP of the caller
recycled
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling return
global stack
VM command:
return
states of other functions
up the calling chain
Assembly code (generated by the translator):
return value
endFrame = LCL
// endframe is a temporary variable
retAddr = *(endFrame – 5) // gets the return address
*ARG = pop()
// repositions the return value for the caller
SP = ARG + 1
// repositions SP of the caller
THAT = *(endFrame – 1)
// restores THAT of the caller
THIS = *(endFrame – 2)
// restores THIS of the caller
ARG = *(endFrame – 3)
// restores ARG of the caller
LCL = *(endFrame – 4)
// restores LCL of the caller
goto retAddr
// goes to the caller’s return address
recycled
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Handling return
global stack
VM command:
return
states of other functions
up the calling chain
Assembly code (generated by the translator):
return value
endFrame = LCL
// endframe is a temporary variable
retAddr = *(endFrame – 5) // gets the return address
*ARG = pop()
// repositions the return value for the caller
SP = ARG + 1
// repositions SP of the caller
THAT = *(endFrame – 1)
// restores THAT of the caller
THIS = *(endFrame – 2)
// restores THIS of the caller
ARG = *(endFrame – 3)
// restores ARG of the caller
LCL = *(endFrame – 4)
// restores LCL of the caller
goto retAddr
// goes to the caller’s return address
Net impact: the caller is back in
business, with the return value
at the top of the stack
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Function call and return
VM code
function Foo.main 4
...
// computes –(19 * (local 3))
push constant 19
push local 3
call Bar.mult 2
neg
...
VM translator
function Bar.mult 2
// Computes the product of the first two
// arguments and puts the result in local 1
...
push local 1
// return value
return
Generated assembly code
(Foo.main)
// assembly code that handles the setting up of
// a function’s execution
...
// assembly code that handles push constant 19
// assembly code that handles push local 3
// assembly code that saves the caller’s state,
// handles some pointers, and then:
goto Bar.mult
// (in assembly)
(Foo$ret.1)
// assembly code that handles neg
...
(Bar.mult)
// assembly code that handles the setting up of
// a function’s execution
...
// assembly code that handles push local 1
// Assembly code that moves the return value to the
// caller, reinstates the caller’s state, and then:
goto Foo$ret.1
// (in assembly)
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Recap
• We showed how to generate the
assembly code that, when
executed, will end up building
and maintaining the global stack
during run-time
global stack
states of other functions
up the calling chain
return value
• This code will implement the
function call-and-return
commands and behavior
• The code is language- and
platform-independent
• It can be implemented in any
machine language.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
VM language
Arithmetic / Logical commands
add
Branching commands
label label
sub
neg
goto label
eq
if-goto label
gt
lt
and
or
not
Memory access commands
Function commands
function functionName nVars
call functionName nArgs
return
pop segment i
push segment i
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Virtual machine: lecture plan
Overview
• Program control
Branching
• Abstraction
• Implementation
Functions
Implementing function call-and-return:
• Implementation overview
• Run-time simulation
• Detailed implementation
VM implementation on the Hack platform:
• Standard mapping
• Abstraction
• VM translator:
proposed implementation
• Implementation
• Project 8 overview
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The big picture: program compilation and translation
myProg directory
myProg directory
Foo.jack
myProg.asm
Foo.vm
class Foo
function Foo.main
function main {. . . }
method bla {. . . }
...
function Foo.bla
...
}
Bar.jack
compiler
class Bar
constructor new {. . . }
method bla {. . . }
}
myProg directory
(Foo.main)
...
(Foo.bla)
VM translator
Bar.vm
...
(Bar.new)
function Bar.new
...
...
function Bar.bla
...
• Compiling a program directory:
> JackCompiler directoryName
• Translating a program directory:
> VMTranslator directoryName
(Bar.bla)
...
(later in the course)
The VM translator
developed in projects 7-8
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Booting
VM program convention
• one file in any VM program is expected to be named Main.vm;
• one VM function in this file is expected to be named main
VM implementation conventions
• the stack starts in address 256 in the host RAM
• when the VM implementation starts running, or is reset,
it starts executing an argument-less OS function named Sys.init
• Sys.init is designed to call Main.main, and then enter an infinite loop
These conventions are realized by the following code:
// Bootstrap code (should be written in assembly)
SP = 256
call Sys.init
In the Hack platform, this code
should be put in the ROM,
starting at address 0
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Standard mapping of the VM on the Hack platform
Hack RAM
Hack RAM
VM
implementation
24576
24577
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Special symbols in translated VM programs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Special symbols in translated VM programs
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Virtual machine: lecture plan
Overview
• Program control
Branching
• Abstraction
• Implementation
Functions
Implementing function call-and-return:
• Implementation overview
• Run-time simulation
• Detailed implementation
VM implementation on the Hack platform:
• Standard mapping
• Abstraction
• VM translator:
proposed implementation
• Implementation
• Project 8 overview
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code (example)
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
VM
translator
function Foo.bar 2
...
push local 4
return
...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code (example)
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
VM
translator
function Foo.bar 2
...
push local 4
return
...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code (example)
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
VM
translator
...
// push constant 17
@17
D=A
... // additional assembly commands that complete the
// implementation of push constant 17
function Foo.bar 2
...
push local 4
return
...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
VM
translator
...
// push constant 17
@17
D=A
... // additional assembly commands that complete the
// implementation of push constant 17
function Foo.bar 2
...
push local 4
return
...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
function Foo.bar 2
...
VM
translator
...
// push constant 17
@17
D=A
... // additional assembly commands that complete the
// implementation of push constant 17
// goto LOOP
... // generated assembly code that implements goto LOOP
push local 4
return
...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
function Foo.bar 2
...
VM
translator
...
// push constant 17
@17
D=A
... // additional assembly commands that complete the
// implementation of push constant 17
// goto LOOP
... // generated assembly code that implements goto LOOP
push local 4
return
...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
function Foo.bar 2
...
push local 4
return
VM
translator
...
// push constant 17
@17
D=A
... // additional assembly commands that complete the
// implementation of push constant 17
// goto LOOP
... // generated assembly code that implements goto LOOP
// call Foo.bar 3
... // generated ... code that implements call Foo.bar 3
...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
function Foo.bar 2
...
push local 4
return
VM
translator
...
// push constant 17
@17
D=A
... // additional assembly commands that complete the
// implementation of push constant 17
// goto LOOP
... // generated assembly code that implements goto LOOP
// call Foo.bar 3
... // generated ... code that implements call Foo.bar 3
...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
function Foo.bar 2
...
push local 4
return
VM
translator
...
// push constant 17
@17
D=A
... // additional assembly commands that complete the
// implementation of push constant 17
// goto LOOP
... // generated assembly code that implements goto LOOP
// call Foo.bar 3
... // generated ... code that implements call Foo.bar 3
...
// function Foo.bar 2
... // generated ... that implements function Foo.bar 2
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
function Foo.bar 2
...
push local 4
return
VM
translator
...
// push constant 17
@17
D=A
... // additional assembly commands that complete the
// implementation of push constant 17
// goto LOOP
... // generated assembly code that implements goto LOOP
// call Foo.bar 3
... // generated ... code that implements call Foo.bar 3
...
// function Foo.bar 2
... // generated ... that implements function Foo.bar 2
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
function Foo.bar 2
...
push local 4
return
VM
translator
...
// push constant 17
@17
D=A
... // additional assembly commands that complete the
// implementation of push constant 17
// goto LOOP
... // generated assembly code that implements goto LOOP
// call Foo.bar 3
... // generated ... code that implements call Foo.bar 3
...
// function Foo.bar 2
... // generated ... that implements function Foo.bar 2
// push local 4
... // generated ... that implements push local 4
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
function Foo.bar 2
...
push local 4
return
VM
translator
...
// push constant 17
@17
D=A
... // additional assembly commands that complete the
// implementation of push constant 17
// goto LOOP
... // generated assembly code that implements goto LOOP
// call Foo.bar 3
... // generated ... code that implements call Foo.bar 3
...
// function Foo.bar 2
... // generated ... that implements function Foo.bar 2
// push local 4
... // generated ... that implements push local 4
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
function Foo.bar 2
...
push local 4
return
VM
translator
...
// push constant 17
@17
D=A
... // additional assembly commands that complete the
// implementation of push constant 17
// goto LOOP
... // generated assembly code that implements goto LOOP
// call Foo.bar 3
... // generated ... code that implements call Foo.bar 3
...
// function Foo.bar 2
... // generated ... that implements function Foo.bar 2
// push local 4
... // generated ... that implements push local 4
// return
... // generated assembly code that implements return
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
VM code (example)
Generated assembly code
...
push constant 17
goto LOOP
...
call Foo.bar 3
...
VM
translator
function Foo.bar 2
...
push local 4
return
...
// push constant 17
@17
D=A
... // additional assembly commands that complete the
// implementation of push constant 17
// goto LOOP
... // generated assembly code that implements goto LOOP
// call Foo.bar 3
... // generated ... code that implements call Foo.bar 3
...
// function Foo.bar 2
... // generated ... that implements function Foo.bar 2
The VM translator:
• An extension of the basic VM
translator written in project 7
• Adds the implementation of the
branching and function commands
// push local 4
... // generated ... that implements push local 4
// return
... // generated assembly code that implements return
...
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
Source language:
Target language:
compiler
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The VM translator
myProg directory
myProg directory
Foo.vm
myProg.asm
function Foo.main
...
function Foo.bla
...
(Foo.main)
...
VM translator
Bar.vm
function Bar.new
...
function Bar.bla
...
(Foo.bla)
...
(Bar.new)
...
(Bar.bla)
...
Proposed design:
• Parser:
parses each VM command into its lexical elements
• CodeWriter: writes the assembly code that implements the parsed command
• Main:
drives the process (VMTranslator)
same design as the basic VM
translator built in project 7
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Main
Input: q fileName.vm : the name of a single source file, or
q directoryName: the name of a directory containing one or more .vm source files
Output:
q
fileName.asm file, or
q
directoryName.asm file
Process:
• Constructs a CodeWriter
• If the input is a .vm file:
q
Constructs a Parser to handle the input file
q
Marches through the input file, parsing each line and generating code from it
• If the input is a directory:
q
Handles every .vm file in the directory in the manner described above.
Implementation note:
An extension of the Main program written in project 7.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Parser
•
Handles the parsing of a single .vm file
•
Reads a VM command, parses the command into its lexical components,
and provides convenient access to these components
•
Removes all white space and comments.
Implementation notes
•
Same Parser that was implemented in project 7
•
If the Parser that you’ve developed in project 7 does not handle the parsing
of the VM commands goto, if-goto, label, call, function, and return,
add this parsing functionality now.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
CodeWriter
The API of the basic CodeWriter (developed in project 7):
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
CodeWriter
Additional functionality:
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
CodeWriter
Additional functionality:
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
CodeWriter
Additional functionality:
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
CodeWriter
Additional functionality:
The generated
assembly code
must follow the
guidelines and
symbols
described in the
“standard
mapping of the
VM on the Hack
platform”
contract.
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Virtual machine: lecture plan
Overview
• Program control
Branching
• Abstraction
• Implementation
Functions
Implementing function call-and-return:
• Implementation overview
• Run-time simulation
• Detailed implementation
VM implementation on the Hack platform:
• Standard mapping
• Abstraction
• VM translator:
proposed implementation
• Implementation
• Project 8 overview
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The big picture
Human
Thought
write a
program
abstraction
high-level
language
OS
compiler
abstraction
VM Code
VM
translator
abstraction
machine
language
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The big picture
Human
Thought
write a
program
abstraction
p9
high-level
language
OS
p12
compiler
abstraction
p10
p11
VM
translator
VM Code
abstraction
p7
p8
machine
language
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The big picture
Human
Thought
write a
program
abstraction
p9
high-level
language
OS
p12
compiler
abstraction
p10
p11
VM
translator
VM Code
abstraction
p7
p8
machine
language
Objective: build a VM translator that translates programs written in
the VM language into programs written in the Hack
assembly language
To test the translator:
Run the generated nachine-level code on the target platform:
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
The big picture
Human
Thought
write a
program
abstraction
p9
high-level
language
OS
p12
compiler
abstraction
p10
p11
VM
translator
VM Code
abstraction
p7
p8
machine
language
Objective: build a VM translator that translates programs written in
the VM language into programs written in the Hack
assembly language
To test the translator:
Run the generated nachine-level code on the target platform:
CPU
or
emulat
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
q
FibonacciElement
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: BasicLoop
ProgramFlow:
u
BasicLoop
BasicLoop.vm
BasicLoopVME.tst
BasicLoop.tst
Testing routine
• Load and run XxxVME.tst on the VM emulator;
• This script loads Xxx.vm into the VM emulator,
allowing you to experiment with its code
BasicLoop.cmp
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: BasicLoop
ProgramFlow:
u
BasicLoop
BasicLoop.vm
BasicLoopVME.tst
BasicLoop.tst
BasicLoop.cmp
q
FibonacciSeries
Testing routine
• Load and run XxxVME.tst on the VM emulator;
• This script loads Xxx.vm into the VM emulator,
allowing you to experiment with its code
• Use your VM translator to translate Xxx.vm;
• The result will be a file named Xxx.asm
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: BasicLoop
ProgramFlow:
u
BasicLoop
BasicLoop.vm
BasicLoopVME.tst
BasicLoop.tst
BasicLoop.cmp
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
Testing routine
• Load and run XxxVME.tst on the VM emulator;
• This script loads Xxx.vm into the VM emulator,
allowing you to experiment with its code
• Use your VM translator to translate Xxx.vm;
• The result will be a file named Xxx.asm
• Load and run Xxx.tst on the CPU emulator;
• This script is designed to load Xxx.asm,
execute it, and compares its output to Xxx.cmp
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: BasicLoop
BasicLoop.vm
ProgramFlow:
u
BasicLoop
BasicLoop.vm
BasicLoopVME.tst
BasicLoop.tst
BasicLoop.cmp
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: BasicLoop
BasicLoop.vm
ProgramFlow:
u
BasicLoop
// Computes the sum 1 + 2 + ... + argument[0],
// and pushes the result onto the stack.
BasicLoop.vm
BasicLoopVME.tst
BasicLoop.tst
BasicLoop.cmp
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: BasicLoop
BasicLoop.vm
ProgramFlow:
u
BasicLoop
BasicLoop.vm
BasicLoopVME.tst
// Computes the sum 1 + 2 + ... + argument[0],
// and pushes the result onto the stack.
// The translated version, BasicLoop.asm (not shown here), can be tested on
// the CPU emulator.
BasicLoop.tst
BasicLoop.cmp
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: BasicLoop
BasicLoop.vm
ProgramFlow:
u
BasicLoop
BasicLoop.vm
BasicLoopVME.tst
BasicLoop.tst
BasicLoop.cmp
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
StaticsTest
Typical loop logic:
while (counter > 0) {
sum += counter
counter-- }
// Computes the sum 1 + 2 + ... + argument[0],
// and pushes the result onto the stack.
// The translated version, BasicLoop.asm (not shown here), can be tested on
// the CPU emulator.
// This can be done using BasicLoop.tst. This script initializes the VM
// memory segments as well as argument[0], and then loads and executes
// BasicLoop.asm.
push constant 0
pop local 0
// initialize sum = 0
label LOOP_START
push argument 0
push local 0
add
pop local 0
// sum = sum + counter
push argument 0
push constant 1
sub
pop argument 0
// counter-push argument 0
if-goto LOOP_START // if counter > 0, goto LOOP_START
push local 0
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: BasicLoop
BasicLoop.vm
ProgramFlow:
u
BasicLoop
BasicLoop.vm
BasicLoopVME.tst
BasicLoop.tst
BasicLoop.cmp
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
StaticsTest
Typical loop logic:
while (counter > 0) {
sum += counter
counter-- }
Designed to test the handling
of the VM commands:
// Computes the sum 1 + 2 + ... + argument[0],
// and pushes the result onto the stack.
// The translated version, BasicLoop.asm (not shown here), can be tested on
// the CPU emulator.
// This can be done using BasicLoop.tst. This script initializes the VM
// memory segments as well as argument[0], and then loads and executes
// BasicLoop.asm.
push constant 0
pop local 0
// initialize sum = 0
label LOOP_START
push argument 0
push local 0
add
pop local 0
// sum = sum + counter
push argument 0
push constant 1
sub
pop argument 0
// counter-push argument 0
if-goto LOOP_START // if counter > 0, goto LOOP_START
push local 0
• label
• if-goto
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
q
FibonacciElement
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: FibonacciSeries
FibSeries.vm
ProgramFlow:
q
BasicLoop
u
FibonacciSeries
FibSeries.vm
FibSeriesVME.tst
FibSeries.tst
FibSeries.cmp
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: FibonacciSeries
FibSeries.vm
ProgramFlow:
q
BasicLoop
u
FibonacciSeries
// Computes the first argument[0] elements of the Fibonacci series.
// Puts the elements in the RAM, starting at the address given in argument[1].
FibSeries.vm
FibSeriesVME.tst
FibSeries.tst
FibSeries.cmp
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: FibonacciSeries
FibSeries.vm
ProgramFlow:
q
BasicLoop
u
FibonacciSeries
FibSeries.vm
FibSeriesVME.tst
// Computes the first argument[0] elements of the Fibonacci series.
// Puts the elements in the RAM, starting at the address given in argument[1].
// FibSeries.tst initializes the VM memory segments as well as
// argument[0] and argument[1], and then executes the translated
// machine code, stored in FibSeries.asm, on the CPU emulator.
FibSeries.tst
FibSeries.cmp
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: FibonacciSeries
FibSeries.vm
ProgramFlow:
q
BasicLoop
u
FibonacciSeries
FibSeries.vm
FibSeriesVME.tst
FibSeries.tst
FibSeries.cmp
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
StaticsTest
typical array processing logic:
arr[i] = arr[i-1] + arr[i-2]
// Computes the first argument[0] elements of the Fibonacci series.
// Puts the elements in the RAM, starting at the address given in argument[1].
// FibSeries.tst initializes the VM memory segments as well as
// argument[0] and argument[1], and then executes the translated
// machine code, stored in FibSeries.asm, on the CPU emulator.
push argument 1
pop pointer 1
// that = argument[1]
push constant 0
pop that 0
// first series element = 0
push constant 1
pop that 1
// second series element = 1
...
label MAIN_LOOP_START
push argument 0
if-goto COMPUTE_ELEMENT // if ... goto COMPUTE_ELEMENT
goto END_PROGRAM
// otherwise, goto END_PROGRAM
label COMPUTE_ELEMENT
push that 0
push that 1
add
...
goto MAIN_LOOP_START
label END_PROGRAM
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: FibonacciSeries
FibSeries.vm
ProgramFlow:
q
BasicLoop
u
FibonacciSeries
FibSeries.vm
FibSeriesVME.tst
FibSeries.tst
FibSeries.cmp
FunctionCalls:
q
SimpleFunction
NestedCall
q FibonacciElement
q
q
StaticsTest
typical array processing logic:
arr[i] = arr[i-1] + arr[i-2]
Designed to perform a more
elaborate test of handling the
VM commands:
• label
• goto
• if-goto
// Computes the first argument[0] elements of the Fibonacci series.
// Puts the elements in the RAM, starting at the address given in argument[1].
// FibSeries.tst initializes the VM memory segments as well as
// argument[0] and argument[1], and then executes the translated
// machine code, stored in FibSeries.asm, on the CPU emulator.
push argument 1
pop pointer 1
// that = argument[1]
push constant 0
pop that 0
// first series element = 0
push constant 1
pop that 1
// second series element = 1
...
label MAIN_LOOP_START
push argument 0
if-goto COMPUTE_ELEMENT // if ... goto COMPUTE_ELEMENT
goto END_PROGRAM
// otherwise, goto END_PROGRAM
label COMPUTE_ELEMENT
push that 0
push that 1
add
...
goto MAIN_LOOP_START
label END_PROGRAM
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
q
FibonacciElement
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: SimpleFunction
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
u
SimpleFunction
SimpleFunction.vm
SimpleFunctionVME.tst
SimpleFunction.tst
SimpleFunction.cmp
NestedCall
q FibonacciElement
q
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: SimpleFunction
SimpleFunction.vm
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
u
SimpleFunction
SimpleFunction.vm
SimpleFunctionVME.tst
SimpleFunction.tst
SimpleFunction.cmp
NestedCall
q FibonacciElement
q
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: SimpleFunction
SimpleFunction.vm
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
// Performs a simple (and meaningless) calculation involving local
// and argument values, and returns the result.
FunctionCalls:
u
SimpleFunction
SimpleFunction.vm
SimpleFunctionVME.tst
SimpleFunction.tst
SimpleFunction.cmp
NestedCall
q FibonacciElement
q
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: SimpleFunction
SimpleFunction.vm
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
u
SimpleFunction
SimpleFunction.vm
SimpleFunctionVME.tst
SimpleFunction.tst
SimpleFunction.cmp
NestedCall
q FibonacciElement
q
q
StaticsTest
// Performs a simple (and meaningless) calculation involving local
// and argument values, and returns the result.
// SimpleFunction.tst initializes the VM memory segments as well
// as some argument values, and then executes the translated
// machine code, stored in SimpleFunction.asm, in the CPU emulator.
function SimpleFunction.test 2
push local 0
push local 1
add
not
push argument 0
add
push argument 1
sub
return
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: SimpleFunction
SimpleFunction.vm
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
u
SimpleFunction
SimpleFunction.vm
SimpleFunctionVME.tst
SimpleFunction.tst
SimpleFunction.cmp
NestedCall
q FibonacciElement
q
q
StaticsTest
// Performs a simple (and meaningless) calculation involving local
// and argument values, and returns the result.
// SimpleFunction.tst initializes the VM memory segments as well
// as some argument values, and then executes the translated
// machine code, stored in SimpleFunction.asm, in the CPU emulator.
function SimpleFunction.test 2
push local 0
push local 1
add
not
push argument 0
add
push argument 1
sub
return
Tests the handling of the VM commands:
• function
• return
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: SimpleFunction
SimpleFunction.vm
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
u
SimpleFunction
SimpleFunction.vm
SimpleFunctionVME.tst
SimpleFunction.tst
SimpleFunction.cmp
NestedCall
q FibonacciElement
q
q
StaticsTest
// Performs a simple (and meaningless) calculation involving local
// and argument values, and returns the result.
// SimpleFunction.tst initializes the VM memory segments as well
// as some argument values, and then executes the translated
// machine code, stored in SimpleFunction.asm, in the CPU emulator.
function SimpleFunction.test 2
push local 0
push local 1
add
not
push argument 0
add
push argument 1
sub
return
Tests the handling of the VM commands:
• function
• return
Simple test, since it involves no caller
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
q
FibonacciElement
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: FibonacciElement
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
u
FibonacciElement
Main.vm
> VMTranslator FibonacciElement
Sys.vm
FibElementVME.tst
FibElement.tst
FibElement.cmp
q
Should yield a single output file:
FibonacciElement.asm
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: FibonacciElement
Main.vm
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
u
FibonacciElement
// Main.fibonacci: computes the n'th element of the Fibonacci series,
// recursively. The n value is supplied by the caller, and stored in
// argument 0.
function Main.fibonacci 0
Main.vm
Sys.vm
FibElementVME.tst
FibElement.tst
FibElement.cmp
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: FibonacciElement
Main.vm
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
u
FibonacciElement
Main.vm
Sys.vm
FibElementVME.tst
FibElement.tst
FibElement.cmp
q
StaticsTest
typical recursive logic:
function fib(n):
if n<2 return n
else return fib(n-1)+fib(n-2)
// Main.fibonacci: computes the n'th element of the Fibonacci series,
// recursively. The n value is supplied by the caller, and stored in
// argument 0.
function Main.fibonacci 0
push argument 0
push constant 2
lt
// checks if n<2
if-goto IF_TRUE
goto IF_FALSE
label IF_TRUE
// if n<2 returns n
push argument 0
return
label IF_FALSE
// if n>=2 returns fib(n-2)+fib(n-1)
push argument 0
push constant 2
sub
call Main.fibonacci 1 // computes fib(n-2)
push argument 0
push constant 1
sub
call Main.fibonacci 1 // computes fib(n-1)
add
// returns fib(n-1) + fib(n-2)
return
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: FibonacciElement
Main.vm (abbreviated)
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
u
FibonacciElement
Main.vm
Sys.vm
FibElementVME.tst
FibElement.tst
// Main.fibonacci: computes the n'th element of the Fibonacci series,
// recursively. The n value is supplied by the caller, and stored in
// argument 0.
function Main.fibonacci 0
...
call Main.fibonacci 1 // computes fib(n-2)
push argument 0
push constant 1
sub
call Main.fibonacci 1 // computes fib(n-1)
add
// returns fib(n-1) + fib(n-2)
return
FibElement.cmp
q
StaticsTest
Sys.vm
// Normally,
Sys.init:
pushes n should
onto thecall
stack,
calls Main.main.
Main.fibonacii
Sys.init
the and
function
// to compute the n’th Fibonacci element.
8, we function
use it to call
various
test functions.
// In
TheProject
Sys.init
should
be called
by the bootstrap code.
function Sys.init 0
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: FibonacciElement
Main.vm (abbreviated)
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
u
FibonacciElement
Main.vm
Sys.vm
FibElementVME.tst
FibElement.tst
// Main.fibonacci: computes the n'th element of the Fibonacci series,
// recursively. The n value is supplied by the caller, and stored in
// argument 0.
function Main.fibonacci 0
...
call Main.fibonacci 1 // computes fib(n-2)
push argument 0
push constant 1
sub
call Main.fibonacci 1 // computes fib(n-1)
add
// returns fib(n-1) + fib(n-2)
return
FibElement.cmp
q
StaticsTest
Sys.vm
// Normally,
Sys.init:
pushes n should
onto thecall
stack,
calls Main.main.
Main.fibonacii
Sys.init
the and
function
// to compute the n’th Fibonacci element.
8, we function
use it to call
various
test functions.
// In
TheProject
Sys.init
should
be called
by the bootstrap code.
function Sys.init 0
push constant 4
call Main.fibonacci 1 // test: computes the 4'th Fib. element
label WHILE
goto WHILE
// loops forever
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: FibonacciElement
Main.vm (abbreviated)
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
u
FibonacciElement
Main.vm
Sys.vm
FibElementVME.tst
FibElement.tst
// Main.fibonacci: computes the n'th element of the Fibonacci series,
// recursively. The n value is supplied by the caller, and stored in
// argument 0.
function Main.fibonacci 0
...
call Main.fibonacci 1 // computes fib(n-2)
push argument 0
push constant 1
sub
call Main.fibonacci 1 // computes fib(n-1)
add
// returns fib(n-1) + fib(n-2)
return
FibElement.cmp
q
StaticsTest
• Tests the handling of function,
return, and call (and many other
VM commands)
Sys.vm
// Normally,
Sys.init:
pushes n should
onto thecall
stack,
calls Main.main.
Main.fibonacii
Sys.init
the and
function
// to compute the n’th Fibonacci element.
8, we function
use it to call
various
test functions.
// In
TheProject
Sys.init
should
be called
by the bootstrap code.
function Sys.init 0
push constant 4
call Main.fibonacci 1 // test: computes the 4'th Fib. element
label WHILE
goto WHILE
// loops forever
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: FibonacciElement
Main.vm (abbreviated)
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
u
FibonacciElement
Main.vm
Sys.vm
FibElementVME.tst
FibElement.tst
// Main.fibonacci: computes the n'th element of the Fibonacci series,
// recursively. The n value is supplied by the caller, and stored in
// argument 0.
function Main.fibonacci 0
...
call Main.fibonacci 1 // computes fib(n-2)
push argument 0
push constant 1
sub
call Main.fibonacci 1 // computes fib(n-1)
add
// returns fib(n-1) + fib(n-2)
return
FibElement.cmp
q
StaticsTest
• Tests the handling of function,
return, and call (and many other
VM commands)
• Tests that the VM implementation
(your translator) initializes the
memory segments
Sys.vm
// Normally,
Sys.init:
pushes n should
onto thecall
stack,
calls Main.main.
Main.fibonacii
Sys.init
the and
function
// to compute the n’th Fibonacci element.
8, we function
use it to call
various
test functions.
// In
TheProject
Sys.init
should
be called
by the bootstrap code.
function Sys.init 0
push constant 4
call Main.fibonacci 1 // test: computes the 4'th Fib. element
label WHILE
goto WHILE
// loops forever
• Tests that the the bootsrap code of
the VM implementation initializes
the stack and calls Sys.init
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
q
FibonacciElement
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: NestedCall
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
u
NestedCall
Sys.vm
NestedCallVME.tst
NestedCall.tst
NestedCall.cmp
NestedCall.html
NestedCallStack.html
q
FibonacciElement
q
StaticsTest
• Closes testing gaps between SimpleFunction and
FibonacciElement
• Recommended when SimpleFunction tests
successfully and FibonacciElement fails or crashes
• Self-documented
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
q
FibonacciElement
q
StaticsTest
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: StaticsTest
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
q
FibonacciElement
u
StaticsTest
Class1.vm
Class2.vm
Sys.vm
> VMTranslator StaticsTest
StaticsTestVME.tst
Should yield a single output file:
StaticsTest.tst
StaticsTest.asm
StaticsTest.cmp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: StaticsTest
class1.vm
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
// Stores two supplied arguments in static 0 and static 1
function Class1.set 0
FunctionCalls:
q
SimpleFunction
q
NestedCall
q
FibonacciElement
u
StaticsTest
Class1.vm
Class2.vm
Sys.vm
StaticsTestVME.tst
StaticsTest.tst
StaticsTest.cmp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: StaticsTest
class1.vm
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
q
FibonacciElement
u
StaticsTest
Class1.vm
Class2.vm
Sys.vm
StaticsTestVME.tst
StaticsTest.tst
StaticsTest.cmp
// Stores two supplied arguments in static 0 and static 1
function Class1.set 0
push argument 0
pop static 0
push argument 1
pop static 1
push constant 0
return
// Returns (static 0) – (static 1)
function Class1.get 0
push static 0
push static 1
sub
return
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: StaticsTest
class1.vm
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
q
FibonacciElement
u
StaticsTest
Class1.vm
Class2.vm
Sys.vm
StaticsTestVME.tst
// Stores two supplied arguments in static 0 and static 1
function Class1.set 0
push argument 0
pop static 0
class2.vm
push argument 1
// Stores
two supplied arguments in static 0 and static 1
pop static
1
function
push constant
0 Class2.set 0
push argument 0
return
pop static 0
argument
// Returns (static push
0) – (static
1) 1
pop static
1
function Class1.get
0
constant 0
push static push
0
push static return
1
StaticsTest.tst
StaticsTest.cmp
sub
return
• The two class files have the same logic
// Returns (static 0) – (static 1)
function Class2.get 0
push static 0
push static 1
sub
return
• But, different .vm files should have
different static segments
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: StaticsTest
class1.vm (abbreviated)
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
q
FibonacciElement
u
StaticsTest
Class1.vm
Class2.vm
Sys.vm
// Stores two supplied arguments in static 0 and static 1
function Class1.set 0
...
// Returns (static 0) – (static 1)
function Class1.get 0
class2.vm
...
// Stores two supplied arguments in static 0 and static 1
function Class1.set 0
Sys.vm
...
function Sys.init 0
// Returns (static 0) – (static 1)
function Class1.get 0
...
StaticsTestVME.tst
StaticsTest.tst
StaticsTest.cmp
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Test programs: StaticsTest
class1.vm (abbreviated)
ProgramFlow:
q
BasicLoop
q
FibonacciSeries
FunctionCalls:
q
SimpleFunction
q
NestedCall
q
FibonacciElement
u
StaticsTest
Class1.vm
Class2.vm
Sys.vm
StaticsTestVME.tst
StaticsTest.tst
StaticsTest.cmp
Tests that the static
segments of different files
are handled correctly.
// Stores two supplied arguments in static 0 and static 1
function Class1.set 0
...
// Returns (static 0) – (static 1)
function Class1.get 0
class2.vm
...
// Stores two supplied arguments in static 0 and static 1
function Class1.set 0
Sys.vm
...
function Sys.init 0
// Returns (static 0) – (static 1)
// Calls Class1.set with 6 and 8
function Class1.get 0
push constant 6
...
push constant 8
call Class1.set 2
pop temp 0
// dumps the return value
// Calls Class2.set with 23 and 15
push constant 23
push constant 15
call Class2.set 2
pop temp 0
// dumps the return value
// Checks the two resulting static segments
call Class1.get 0
call Class2.get 0
label WHILE
// loops forever
goto WHILE
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
Tools and resources
• Test programs and compare files: nand2tetris/projects/08
• Reference: chapter 8 in The Elements of Computing Systems
Same as in project 7:
• Experimenting with the test VM programs: the supplied VM emulator
• Translating the test VM programs into assembly: your VM translator
• Testing the resulting assembly code: the supplied CPU emulator
• Programming language for implementing your VM translator: Java, Python, ...
• Tutorials: VM emulator, CPU emulator (nand2tetris web site).
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
• Chapter 8
• Virtual Machine, Part II
These slides support chapter 8 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken
CO557: The Jack Language
David Barnes
Chapter 9
Features of the Language
These slides support chapter 9 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Overview
• An introduction to the features of the Jack language.
• A comparison with other languages, such as Java.
• A critique of some of its features.
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Jack in a nutshell
/** Demo: working with Point objects. */
class Main {
function void main() {
var Point p1, p2, p3;
let p1 = Point.new(1,2);
let p2 = Point.new(3,4);
let p3 = p1.plus(p2);
do p3.print();
do Output.println();
do Output.printInt(p1.distance(p3));
return;
}
}
/** Represents a Point object. */
class Point {
field int x, y;
static int pointCount;
/** Constructs a new point */
constructor Point new(int ax, int ay) {
let x = ax;
let y = ay;
let pointCount = pointCount + 1;
return this;
}
// More Point methods...
}
•
A simple, Java-like language.
•
Object-based, no inheritance.
•
Multi-purpose.
•
Lends itself to interactive apps.
•
Can be learned in about an hour.
•
The syntax is regular for the sake of
the parser.
Lack of strong typing makes the
language closer to C than Java in
some ways.
Lack of automated garbage collection.
•
•
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Take home lessons
An inside view of how high-level OO languages ...
•
are designed
•
handle primitive types and class types
•
create, represent, and dispose objects
•
deal with strings, arrays, and lists
•
interact with the host OS
•
... and many more issues
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Hello world
/** Hello World program. */
class Main {
function void main() {
/* Prints some text using the standard library. */
How many numbers? 3
Hello
world! 12
Enter
a number:
EnterFraction
a number: 8 API
Enter a number: 5
The average is 8
do Output.printString(”Hello world!”);
do Output.println();
// New line
return;
}
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Language constructs
• Comments:
/** Hello World program. */
class Main {
function void main() {
/* Prints some text using the standard library. */
do Output.printString(”Hello world!”);
do Output.println();
return;
// New line
How many numbers? 3
EnterAPI
a number:
q /**
block12comment */
Enter a number: 8
q /*
block
comment
*/
Enter
a number:
5
The average is 8
q // in-line comment
• White space acts as a separator.
}
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Language constructs
Jack code
// Inputs some numbers and computes their average
class Main {
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
}
do Output.printString(”The average is ”);
do Output.printInt(sum / length);
return;
}
}
• A Jack program is a
collection of one or
more Jack classes,
one of which must be
named Main
• The Main class must
have at least one
function, named main
• Program’s entry point:
Main.main
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
How many numbers? 3
Fraction
API
Enter
a number:
12
Enter a number: 8
Enter a number: 5
The average is 8
Language constructs
Jack code
// Inputs some numbers and computes their average
class Main {
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
}
do Output.printString(”The average is ”);
do Output.printInt(sum / length);
return;
}
}
Jack data types:
• Primitive:
• int
• char
• boolean
• Class types:
• OS: Array, String, ...
• Additional ADT’s can be
defined and used, as
needed
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
How many numbers? 3
Fraction
API
Enter
a number:
12
Enter a number: 8
Enter a number: 5
The average is 8
Language constructs
Jack code
// Inputs some numbers and computes their average
class Main {
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
}
do Output.printString(”The average is ”);
do Output.printInt(sum / length);
return;
}
}
How many numbers? 3
Fraction
API
Enter
a number:
12
Enter a number: 8
Enter a number: 5
The average is 8
Flow of control:
• if / if...else
• while
• do
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Language constructs
Jack code
// Inputs some numbers and computes their average
class Main {
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
}
do Output.printString(”The average is ”);
do Output.printInt(sum / length);
return;
}
}
Arrays:
• Array is implemented as
part of the standard class
library
• Jack arrays are not typed
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
How many numbers? 3
Fraction
API
Enter
a number:
12
Enter a number: 8
Enter a number: 5
The average is 8
Language constructs
Jack code
// Inputs some numbers and computes their average
class Main {
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
}
do Output.printString(”The average is ”);
do Output.printInt(sum / length);
return;
}
}
OS services:
• Keyboard.readInt
• Output.printString
• Output.printInt
•
More...
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
How many numbers? 3
Fraction
API
Enter
a number:
12
Enter a number: 8
Enter a number: 5
The average is 8
OO programming: building a class
Fraction class
/** Represents the Fraction type and related operations. */
class Fraction {
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
OO programming: fields and accessors
Fraction class
/** Represents the Fraction type and related operations. */
class Fraction {
field, aka property,
aka member variable
field int numerator, denominator;
/** Accessors. */
method int getNumerator() {
return numerator;
}
the only way to access field
values from outside the
class is through accessors
method int getDenominator() {
return denominator;
}
// More Fraction methods follow.
} // Fraction class
Some Jack class
class Foo {
...
var Fraction x;
let x = Fraction.new(5,17);
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
OO programming: fields and accessors
Fraction class
/** Represents the Fraction type and related operations. */
class Fraction {
field, aka property,
aka member variable
field int numerator, denominator;
/** Accessors. */
method int getNumerator() {
return numerator;
}
the only way to access field
values from outside the
class is through accessors
method int getDenominator() {
return denominator;
}
// More Fraction methods follow.
} // Fraction class
Some Jack class
class Foo {
...
var Fraction x;
let x = Fraction.new(5,17);
do Output.printInt(x.numerator);
// not allowed
do Output.printInt(x.getNumerator());
// ok
...
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
OO programming: subroutines – constructor, method, function
Fraction class
/** Represents the Fraction type and related operations. */
class Fraction {
field int numerator, denominator;
/** Constructs a (reduced) fraction from the given numerator and denominator. */
constructor Fraction new(int x, int y) {
let numerator = x; let denominator = y;
do reduce();
// reduces the fraction
return this;
// returns the base address of the new object
}
• this: a reference to the current object
Jack subroutines:
• methods
• constructors
• functions
(base address)
// Reduces this fraction.
• a constructor must return the (base
method void reduce() {
address of) the newly created object
var int g;
let g = Fraction.gcd(numerator, denominator);
if (g > 1) {let numerator = numerator / g; let denominator = denominator / g;}
return;
a subroutine must terminate with a return command
}
}
// Computes the greatest common divisor of the given integers.
function int gcd(int a, int b) {
var int r;
while (~(b = 0)) {
// applies Euclid’s algorithm.
let r = a – (b * (a / b)); // r = remainder of the integer division a/b
let a = b; let b = r; }
return a;
}
// More Fraction code in next slide
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
OO programming: memory management
Fraction class
/** Represents the Fraction type and related operations. */
class Fraction {
field int numerator, denominator;
/** Disposes this fraction. */
method void dispose() {
do Memory.deAlloc(this);
return;
}
// uses an OS routine to recycle the object’s memory.
} // Fraction class
Garbage collection
• Jack has no garbage collection
• Objects must be disposed explicitly
• Best practice: every class that has a constructor should also feature a
dispose method.
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
NB: There are no safeguards to
prevent access to deallocated
memory.
OO programming: object representation
Fraction class
RAM
...
/** Represents the Fraction type and related operations. */
class Fraction {
256
...
field int numerator, denominator;
/** Constructs a (reduced) fraction from the given numerator and denominator */
constructor Fraction new(int x, int y) {
let numerator = x; let denominator = y;
do reduce();
The compiled constructor’s VM code
return this;
includes OS calls that allocate and manage
}
RAM space for representing the new object
// More Fraction methods
...
var Fraction a, b, c;
...
let a = Fraction.new(2,3);
let b = Fraction.new(1,5);
...
a
4112
b
2047
2048
...
Issues:
• allocating memory
• de-allocating memory
(handled by the compiler
and the OS)
The client’s view
4112
1
4113
...
5
15087
2
15088
...
3
heap
16383
...
2
3
1
stack
...
}
Client code
15087
5
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
NB: Effect of deallocation is
undefined.
OO programming: object representation
RAM
...
256
...
15087
a
4112
b
stack
...
2047
2048
Implementation
...
Abstraction
4112
1
4113
...
5
15087
2
15088
...
3
heap
16383
...
2
3
1
5
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Syntax
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Syntax elements:
• White space / comments
• keywords
• Symbols
• Constants
• Identifiers
}
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Syntax: white space / comments
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Syntax elements:
• White space / comments
• keywords
• Symbols
• Constants
• Identifiers
}
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Syntax: white space / comments
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Syntax elements:
• White space / comments
• keywords
• Symbols
• Constants
• Identifiers
}
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Syntax: keywords
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Syntax elements:
• White space / comments
• keywords
• Symbols
• Constants
• Identifiers
}
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Syntax: keywords
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Syntax elements:
• White space / comments
• keywords
• Symbols
• Constants
• Identifiers
}
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Syntax: symbols
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Syntax elements:
• White space / comments
• keywords
• Symbols
• Constants
• Identifiers
}
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Syntax: symbols
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Syntax elements:
• White space / comments
• keywords
• Symbols
• Constants
• Identifiers
}
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Syntax: constants
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Syntax elements:
• White space / comments
• keywords
• Symbols
• Constants
• Identifiers
}
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Syntax: constants
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Syntax elements:
• White space / comments
• keywords
• Symbols
• Constants
• Identifiers
}
...
}
NB: No character literals: ‘a’
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Syntax: identifiers
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Syntax elements:
• White space / comments
• keywords
• Symbols
• Constants
• Identifiers
}
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Syntax: identifiers
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Syntax elements:
• White space / comments
• keywords
• Symbols
• Constants
• Identifiers
}
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Recap
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Syntax elements:
• White space / comments
• keywords
• Symbols
• Constants
• Identifiers
}
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Data types
/** Procedural processing example */
class Main {
/* Inputs some numbers and computes their average */
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
Primitive types
q
int:
Non-negative 2’s-complement
16-bit integer, i.e. an integer
in the range 0,..., 32767
q
boolean:
true or false
q
char:
Integer values representing
characters
}
...
}
Class types
•
OS types: String, Array
•
User-defined types:
Fraction, List, ...
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Type conversions
Characters and integers can be converted into each other, as needed:
var char c; var String s;
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Type conversions
Characters and integers can be converted into each other, as needed:
var char c; var String s;
let c = 65;
// 'A'
let c = 'A'; // Not supported by the Jack language
let s = "A";
let c = s.charAt(0);
// 'A', ok
An integer can be assigned to a reference variables, in which case it is treated as a memory address:
var Array arr;
// creates a pointer variable
• Lack of strict typing is a significant
feature.
• Simplifies the ‘front end’ dramatically.
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Type conversions
Characters and integers can be converted into each other, as needed:
var char c; var String s;
let c = 65;
// 'A'
let c = 'A'; // Not supported by the Jack language
let s = "A";
let c = s.charAt(0);
// 'A', ok
An integer can be assigned to a reference variables, in which case it is treated as a memory address:
var Array arr;
// creates a pointer variable
let arr = 5000;
// ok...
let arr[100] = 17; // sets memory address 5100 to 17
• Lack of strict typing is a significant
feature.
• Simplifies the ‘front end’ dramatically.
An object can be converted into an Array, and vice versa:
var Array arr;
let arr = Array.new(2);
let arr[0] = 2; let arr[1] = 5;
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Type conversions
Characters and integers can be converted into each other, as needed:
var char c; var String s;
let c = 65;
// 'A'
let c = 'A'; // Not supported by the Jack language
let s = "A";
let c = s.charAt(0);
// 'A', ok
An integer can be assigned to a reference variables, in which case it is treated as a memory address:
var Array arr;
// creates a pointer variable
let arr = 5000;
// ok...
let arr[100] = 17; // sets memory address 5100 to 17
• Lack of strict typing is a significant
feature.
• Simplifies the ‘front end’ dramatically.
An object can be converted into an Array, and vice versa:
var Array arr;
let arr = Array.new(2);
let arr[0] = 2; let arr[1] = 5;
var Fraction x; // a Fraction object has two int fields: numerator and denominator.
let x = arr;
// sets x to the base address of the memory block representing the array [2,5]
do x.print()
// prints 2/5 (using the print method of the Fraction class)
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Review
• We have looked at the basic language features of Jack.
• It supports object-based programming.
• Instance variables and static variables are supported.
• Instance methods and static methods are supported.
• Its syntactic structure will make the task of parsing
relatively easy.
• Its ‘wordy’ and prescriptive syntactic structure is painful for
a programmer.
• Its lack of proper typing makes it closer to C than Java in
some respects.
• Its approach to heap management is risky.
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
CO557: The Jack Language
David Barnes
Chapter 9
Syntax and the API/OS
These slides support chapter 9 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Jack application
• A Jack program, or application, is a collection of one or more Jack
classes, one of which must be named Main
• The Main class must have at least one function, named main
• Program’s entry point: Main.main
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Classes
• Class = basic compilation unit
• Each class Foo is stored in a separate Foo.jack file
• The class name’s first character must be an uppercase letter.
Foo.jack file
class Foo {
field variable declarations
static variable declarations
must precede
the subroutine
declarations
subroutine declarations
}
constructors,
methods,
functions
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Classes that represent entities (objects)
• Examples: Fraction, List, String, ...
• A class that contains at least one method
• Used to represent an object type and operations on this object
• Typically contains fields and methods
• Can also contain functions, recommended for “helper” purpose only
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Utility classes
• A class that contains only functions (“static methods”)
can be called a “utility class”
•
(no fields, constructors, or methods)
• Offers a “library of services”
Math class API (example)
Provides various mathematical operations.
•
function int abs(int x): returns the absolute value of x.
•
function int multiply(int x, int y): returns the product of x and y.
•
function int divide(int x, int y): returns the integer part of x/y.
•
function int min(int x, int y): returns the minimum of x and y.
•
function int max(int x, int y): returns the maximum of x and y.
•
function int sqrt(int x): returns the integer part of the square root of x.
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Jack’s standard class library / OS
Jack code
// Inputs some numbers and computes their average
class Main {
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
}
do Output.printString(”The average is ”);
do Output.printInt(sum / length);
return;
}
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Jack’s standard class library / OS
Jack code
// Inputs some numbers and computes their average
class Main {
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt(”How many numbers? ”);
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt(”Enter a number: ”);
let sum = sum + a[i];
let i = i + 1;
}
do Output.printString(”The average is ”);
do Output.printInt(sum / length);
return;
}
}
OS purpose:
How many numbers? 3
• Closes
gaps 12
between
Enter a number:
Enter a number:
8
high-level
programs
and
Enter a number: 5
the
host hardware
The average
is 8
• Provides efficient
implementations of
commonly-used
functions
• Provides efficient
implementations of
commonly-used ADTs
OS implementation:
• A collection of classes
• Similar to Java’s standard
class library
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Jack’s standard class library / OS
Complete OS API: Nand2Tetris book / website
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Classes: syntax
class Foo {
field variable declarations
static variable declarations
subroutine declarations
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Subroutines
Subroutine declaration
constructor | method | function
type subroutineName (parameter-list) {
local variable declarations
statements
}
Jack subroutines
• Constructors: create new objects
• Methods: operate on the current object
• Functions: static methods
Subroutine types and return values
• Method and function type can be either void, a primitive data type, or a class name
• Each subroutine must end with return value or return.
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Constructors
Constructor declaration
constructor ClassName constructorName (parameter-list) {
local variable declarations
statements
}
Constructors
•
0, 1, or more in a class
•
Common name: new
•
The constructor’s type must be the
name of the constructor’s class
•
The constructor must return a
reference to an object of the class type.
class Point {
field int x;
field int y;
...
/* Creates a Point. */
constructor Point new(int ax, int ay) {
let x = ax;
let y = ay;
return this;
}
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Variables
Variable kinds:
q
q
q
q
field variables:
object properties, can be manipulated by the
class constructors and methods
static variables:
class-level variables,
can be manipulated by the class subroutines
local variables:
used by subroutines, for local computations
parameter variables:
used to pass values to subroutines,
behave like local variables
/** Represents a Point object. */
class Point {
field int x, y;
static int pointCount;
...
method int bla(int z) {
int foo;
let foo = z * (x + y);
return foo;
}
...
}
Variables must be ...
• Declared before they are used
• Typed.
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Variables
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Statements: syntax
return
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Expressions
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Expressions
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Expressions
NB: expression is defined
recursively (in terms of
itself).
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Expressions
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Expressions
NB: No defined order of
evaluation! Leads to
inconsistent
implementations.
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Subroutine calls
Examples:
class Foo {
...
method void f() {
var Bar b;
// declares a local variable of class type Bar
var int i;
...
// declares a local variable of primitive type int
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Subroutine calls
Examples:
class Foo {
...
method void f() {
var Bar b;
// declares a local variable of class type Bar
var int i;
...
// declares a local variable of primitive type int
do g();
// calls method g of the current class on this object
do Foo.p(3);
// calls function p of the current class
do Bar.h();
// calls function h of class Bar
let b = Bar.r(); // calls function or constructor r of class Bar
do b.q();
// calls method q of class Bar on the b object
let i = w(b.s(), Foo.t()); // calls method w on this object. The arguments are
// the results of calling method s on object b,
// and function or constructor t of class Foo
...
}
}
Subroutine call syntax: subroutineName(argument-list)
• The number and type of arguments must agree with those of the subroutine’s parameters.
• Each argument can be an expression of unlimited complexity.
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
NB: requirement to check
match between formal and
actual parameters.
Strings
Examples:
...
var String s;
// Creates an object variable (pointer), initialized to null
var char c;
// Creates a primitive variable, initialized to zero
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Strings
Examples:
...
var String s;
// Creates an object variable (pointer), initialized to null
var char c;
// Creates a primitive variable, initialized to zero
...
// Suppose we want s to refer to the string “Hello World!”:
let s = String.new(12);
// Followed by a loop that uses String’s appendChar method to set s to “Hello World!”
// (loop code not shown)
NB: assumption that Strings can grow
in length.
Difficult to implement in practice in
view of the memory management.
// Alternatively, the Jack compiler allows using:
let s = ”Hello World”;
// “syntactic sugar”
// Accessing some character within a string:
let c = s.charAt(6);
// Sets c to the numeric value representing ‘W’.
For more String and character operations, see the String class API
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
capacity of this String?
Arrays: untyped
Examples:
...
var Array arr;
var String helloWorld;
let helloWorld = “Hello World!”
...
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Arrays: untyped
Examples:
...
var Array arr;
var String helloWorld;
let helloWorld = “Hello World!”
...
let arr = Array.new(4);
let arr[0] = 12;
let arr[1] = false;
let arr[2] = Fraction.new(314/100);
let arr[3] = helloWorld;
...
• Jack arrays are ...
q
q
q
instances (objects) of the OS class Array
not typed
uni-dimensional
• Multi-dimensional arrays can be obtained by using an arrays of arrays.
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
End note: peculiar features of the Jack language
•
The keyword let:
must be used in assignments: let x = 0;
•
The keyword do:
must be used for calling a method or a function outside an expression:
do reduce();
•
The body of a statement must be within curly brackets, even if it contains a
single statement: if (a > 0) {return a;} else {return –a;}
•
All subroutine must end with a return
•
No operator priority:
q
The following value is unpredictable: 2 + 3 * 4
q
To enforce priority of operations, use parentheses: 2 + (3 * 4)
•
The language is weakly typed.
These concessions make the life of
the compiler writer much easier.
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Developing a Jack application
Put all the app files in one directory, whose name is the app name
Write / edit your Jack class files using a standard text editor
Compile your Jack files / directory using the supplied JackCompiler
(available in nand2tetris/tools)
Execute your app by loading the app directory (which now contains
the compiled .vm files) into the supplied VM emulator,
and running the code
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Running a Jack application
• Compile to VM code.
• Run via the VM emulator.
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Handling output: text
Textual apps:
• Screen: 23 rows of 64 characters, b&w
• Font: featured by the Jack OS
• Output: Jack OS Output class
class Output {
function void moveCursor(int i, int j)
function void printChar(char c)
function void printString(String s)
function void printInt(int i)
function void println()
OS class, for handling
textual output
function void backSpace()
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Handling output: graphics
Graphical apps:
• Screen: 256 rows of 512 pixels, b&w
• Output: Jack OS Screen class (or do your own)
Class Screen {
function void clearScreen()
function void setColor(boolean b)
function void drawPixel(int x, int y)
function void drawLine(int x1, int y1, int x2, int y2)
function void drawRectangle(int x1, int y1, int x2, int y2)
function void drawCircle(int x, int y, int r)
}
OS class, for handling
graphical output
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Handling inputs
Input device:
• Standard keyboard
• Input programming:
• use the OS Keyboard
class
Class Keyboard {
function char keyPressed()
function char readChar()
function String readLine(String message)
function int readInt(String message)
}
OS class, for handling
input from the keyboard
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
The Jack character set
key
code
key
code
key
code
key
code
key
code
(space)
32
0
48
A
65
a
97
newline
128
!
33
1
49
B
66
b
98
backspace
129
“
34
…
…
C
…
c
99
left arrow
130
#
35
9
57
…
…
…
…
up arrow
131
$
36
90
z
122
right arrow
132
37
58
Z
%
:
[
91
{
123
133
38
59
down arrow
&
;
/
92
|
124
134
39
60
home
‘
<
]
93
}
125
135
40
61
end
(
=
^
94
~
126
136
41
62
Page up
)
>
_
95
137
42
63
Page down
*
?
`
96
138
43
64
insert
+
@
delete
139
,
44
esc
140
-
45
f1
141
.
46
…
…
/
47
f12
152
Keyboard.keypress()
returns the code of the currently pressed key,
or 0 when no key is pressed
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
The Jack OS: Math
class Math {
function void init()
function int abs(int x)
function int multiply(int x, int y)
function int divide(int x, int y)
function int min(int x, int y)
function int max(int x, int y)
function int sqrt(int x)
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
The Jack OS: String
Class String {
constructor String new(int maxLength)
method void
dispose()
method int
length()
method char
charAt(int j)
method void
setCharAt(int j, char c)
0 termination (C style)
or length and capacity?
method String appendChar(char c)
method void
eraseLastChar()
method int
intValue()
method void
setInt(int j)
function char backSpace()
function char doubleQuote()
function char newLine()
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
The Jack OS: Array
Class Array {
function Array new(int size)
method void dispose()
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
The Jack OS: Memory
class Memory {
function int peek(int address)
function void poke(int address, int value)
function Array alloc(int size)
function void deAlloc(Array o)
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Allows examination (and
modification) of arbitrary RAM
locations, in effect.
Consider the effect of poke(0, …).
The Jack OS: Sys
Class Sys {
function void halt():
function void error(int errorCode)
function void wait(int duration)
}
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Sample Jack programs
q
Square: a simple, interactive, multi-class OO application
q
Pong: a complete, interactive, multi-class OO application
q
Average: illustrates simple array processing
q
ComplexArrays: illustrates various array manipulations, including
two-dimensional arrays
q
ConvertToBin: illustrates algebraic operations, and working with
peek and poke
Code: nand2tetris/projects/11
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
Review
• We have started to consider the syntactic structure of the
Jack language:
q
The sequence of symbols in classes and subroutines.
• Some ‘semantic’ checks of validity will be required:
Check that a called method exists within the associated class.
q Check that the number (and types?) of parameters in caller and
callee match.
q
• OS (API) classes provide:
q
Utility functionality; e.g., Math.
q
Efficient access to OS features; e.g., Screen, Keyboard.
• Some significant issues:
Order of evaluation of expressions is undefined.
q No array-bound checking.
q String capacity is unclear.
q
Nand to Tetris / www.nand2tetris.org / Chapter 9 / Copyright © Noam Nisan and Shimon Schocken
CO557: Parsing I
David Barnes
Chapter 10
Compiling I
These slides support chapter 10 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
The big picture: compilation
high-level program
class Main {
function void main() {
var Point p1, p2, p3;
let p1 = Point.new(1,2);
let p2 = Point.new(3,4);
let p3 = p1.plus(p2);
do p3.print();
Compiler
// should print (4,6)
do Output.println();
do Output.printInt(p1.distance(p3));
// should print 5
return;
}
}
/** Represents a Point. */
class Point {
field int x, y;
static int pointCount;
/** Constructs a new point */
constructor Point new(int ax,
int ay) {
let x = ax;
let y = ay;
let pointCount =
pointCount + 1;
return this;
}
// ... more Point methods
machine code
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
execute
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
...
(4,6)
5
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Two-tier compilation
high-level program
class Main {
function void main() {
var Point p1, p2, p3;
let p1 = Point.new(1,2);
let p2 = Point.new(3,4);
let p3 = p1.plus(p2);
do p3.print();
Compiler
// should print (4,6)
do Output.println();
do Output.printInt(p1.distance(p3));
// should print 5
return;
}
}
/** Represents a Point. */
class Point {
field int x, y;
static int pointCount;
/** Constructs a new point */
constructor Point new(int ax,
int ay) {
let x = ax;
let y = ay;
let pointCount =
pointCount + 1;
return this;
}
// ... more Point methods
VM code
push local 0
push constant 0
eq
not
push argument 1
neg
push local
VM1translator
call div
pop argument 3
push local 1
neg
push local 0
push local 1
push local 2
add
push constant 2
push local 0
pop argument 1
push local 0
push constant 0
not
push local 1
push local 0
push local 1
add
...
machine code
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000000000000
1111010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
...
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Compiler development roadmap
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Compiler development roadmap
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Compiler development roadmap
We will skip XML generation.
this
chapter
Syntax analyzer implementation:
• Tokenizer
• Parser / compilation engine
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Tokenizing (first approximation)
tokenized input
Prog.jack (input)
...
if (x < 0) {
// prints the sign
let sign = "negative";
}
...
stream of
characters
tokenizing
...
if
(
x
<
0
{
let
sign
=
"negative"
;
}
...
compiler
stream of
tokens
Tokenizing = grouping characters into tokens
A token is a string of characters that has a meaning
A programming language specification must document (among other things)
its allowable tokens.
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack tokens
Prog.jack (input)
...
if (x < 0) {
// prints the sign
let sign = "negative";
}
...
• keywords
• symbols
• integers
• strings
• identifiers
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack tokens
Prog.jack (input)
...
if (x < 0) {
// prints the sign
let sign = "negative";
}
...
keyword:
'class' | 'constructor' | 'function' |
'method' | 'field' | 'static' | 'var' | 'int' |
'char' | 'boolean' | 'void' | 'true' | 'false' |
'null' | 'this' | 'let' | 'do' | 'if' | 'else' |
'while' | 'return’
symbol:
'{' | '}' | '(' | ')' | '[' | ']' | '. ' | ', ' | '; ' | '+' | '-' | '*' |
'/' | '&' | '|' | '<' | '>' | '=' | '~'
integerConstant: a decimal number in the range 0 ... 32767
StringConstant: '"' a sequence of Unicode characters,
not including double quote or newline '"'
identifier: a sequence of letters, digits, and
underscore ( '_' ) not starting with a digit.
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack tokenizer
output
Prog.jack
...
...
if (x < 0) {
// prints the sign
let sign = "negative";
}
...
Tokenizer
keyword:
'class' | 'constructor' | 'function' |
'method' | 'field' | 'static' | 'var' | 'int' |
'char' | 'boolean' | 'void' | 'true' | 'false' |
'null' | 'this' | 'let' | 'do' | 'if' | 'else' |
'while' | 'return’
symbol:
'{' | '}' | '(' | ')' | '[' | ']' | '. ' | ', ' | '; ' | '+' | '-' | '*' |
'/' | '&' | '|' | '<' | '>' | '=' | '~'
integerConstant: a decimal number in the range 0 ... 32767
StringConstant: '"' a sequence of Unicode characters,
not including double quote or newline '"'
identifier: a sequence of letters, digits, and
underscore ( '_' ) not starting with a digit.
Tokenizer:
• Handles the compiler’s input
• Allows advancing the input
• Supplies the current token’s
value and type
• (complete API, later)
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack tokenizer
output
Prog.jack
...
if (x < 0) {
// prints the sign
let sign = "negative";
}
...
Tokenizer
keyword:
'class' | 'constructor' | 'function' |
'method' | 'field' | 'static' | 'var' | 'int' |
'char' | 'boolean' | 'void' | 'true' | 'false' |
'null' | 'this' | 'let' | 'do' | 'if' | 'else' |
'while' | 'return’
symbol:
'{' | '}' | '(' | ')' | '[' | ']' | '. ' | ', ' | '; ' | '+' | '-' | '*' |
'/' | '&' | '|' | '<' | '>' | '=' | '~'
integerConstant: a decimal number in the range 0 ... 32767
StringConstant: '"' a sequence of Unicode characters,
not including double quote or newline '"'
identifier: a sequence of letters, digits, and
underscore ( '_' ) not starting with a digit.
...
<keyword> if </keyword>
<symbol> ( </symbol>
<identifier> x </identifier>
<symbol> < </symbol>
<intConst> 0 </intCons>
<symbol> ) </symbol>
<symbol> { </symbol>
<keyword> let </keyword>
<identifier> sign </identifier>
<symbol> = </symbol>
<stringConst> negative </stringConst>
<symbol> ; </symbol>
<symbol> } </symbol>
...
Tokenizer:
• Handles the compiler’s input
• Allows advancing the input
• Supplies the current token’s
value and type
• (complete API, later)
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Basic lexical process for Jack
char c = skipBlanksAndComments();
if(Character.isAlphabetic(c) || c == ‘_’) {
gather consecutive alphabetic, digits and underscores into a token String;
if(token matches one of the keywords) {
classify as KEYWORD;
}
else {
classify as IDENTIFIER;
}
}
else if(Character.isDigit(c)) {
gather consecutive digits into a token String;
classify as INTEGER;
}
else if(c == ‘”’) {classify as STRING; }
else if(…) { … }
else {
deal with a single character symbol;
}
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Compiler development roadmap
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Compiler development roadmap
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Grammar
A grammar is a set of rules, describing how tokens can be combined to
create valid language constructs
sentence:
nounPhrase verbPhrase
Alternative notation: BNF, Backus-Naur Form
sentence ::= nounPhrase verbPhrase ;
I tend to use something close to BNF
in assessments and exam questions.
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Grammar
A grammar is a set of rules, describing how tokens can be combined to
create valid language constructs
sentence:
Each rule has a
Alternative
left
side and a notation:
right side
nounPhrase verbPhrase
nounPhrase: determiner? noun
verbPhrase:
verb nounPhrase
nounPhrase ::= [ determiner ] noun ;
noun: 'dog' | ’school' | 'dina' | ’he' | ’she' | 'homework’ | ...
verb: 'went' | 'ate' | ’said' | ...
determiner: 'the' | 'to' | 'my’ | ...
...
Items between quote marks are ‘terminal symbols’.
Dina went to school
She said
The dog ate my homework
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
The set of rules can be used in two
distinct ways:
• As a generator.
• As a checker.
Grammar
Jack grammar (subset)
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Grammar
Jack grammar (subset)
statement: ifStatement |
whileStatement |
letStatement
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Grammar
Jack grammar (subset)
Input examples
statement: ifStatement |
whileStatement |
letStatement
statements: statement*
Alternative notation:
ifStatement: 'if' '(' expression ')’
'{' statements '}’
statements ::= { statement } ;
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beginning with a digit
constant: a decimal number
Expressions
17
x
x + 17
x - y
op: '+' | '-' | '=' | '>' | '<'
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Grammar
Jack grammar (subset)
statement: ifStatement |
whileStatement |
letStatement
Input examples
let x = 100;
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beginning with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Grammar
Jack grammar (subset)
statement: ifStatement |
whileStatement |
letStatement
Input examples
let x = 100;
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
let x = x + 1;
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beginning with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Grammar
Jack grammar (subset)
statement: ifStatement |
whileStatement |
letStatement
Input examples
let x = 100;
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
let x = x + 1;
while (n < lim)
let n = n + 1;
}
expression: term (op term)?
term: varName | constant
varName: a string not beginning with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Grammar
Jack grammar (subset)
statement: ifStatement |
whileStatement |
letStatement
Input examples
let x = 100;
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
let x = x + 1;
while (n < lim)
let n = n + 1;
}
expression: term (op term)?
term: varName | constant
varName: a string not beginning with a digit
constant: a decimal number
if (x = 1) {
let x = 100;
let x = x + 1;
}
op: '+' | '-' | '=' | '>' | '<'
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Grammar
Jack grammar (subset)
statement: ifStatement |
whileStatement |
letStatement
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term) *
term: varName | constant
varName: a string not beginning with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
Input examples
while (lim < 100) {
if (x = 1) {
let z = 100;
while (z > 0) {
let z = z – 1;
}
}
let lim = lim + 10;
}
Parsing:
Determining if a given input
conforms to a grammar
In the process, uncovering
the grammatical structure of
the given input.
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
NB: Evidence of recursion in the
definition: a whileStatement
can contain a whileStatement
…
Parse tree
sentence: nounPhrase verbPhrase
nounPhrase: determiner ? noun
verbPhrase: verb nounPhrase
noun: 'dog' | ’school' | 'dina' |
’he' | ’she' | 'homework’ | ...
verb: 'went' | 'ate' | ’said' | ...
determiner:
'the' | 'to' | 'my’ | ...
...
Parsing
• Determine if the given
input conforms to the
grammar
• In the process, construct
the grammatical structure
of the input
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parse tree
sentence: nounPhrase verbPhrase
NB: The parse tree can either be
built ‘bottom up’ or ‘top down’.
nounPhrase: determiner ? noun
verbPhrase: verb nounPhrase
noun: 'dog' | ’school' | 'dina' |
’he' | ’she' | 'homework’ | ...
verb: 'went' | 'ate' | ’said' | ...
determiner:
'the' | 'to' | 'my’ | ...
...
Parsing
• Determine if the given
input conforms to the
grammar
• In the process, construct
the grammatical structure
of the input
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parse tree
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parse tree
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
If the parse tree shows valid input,
the code generator ‘walks’ the tree
to generate equivalent VM code.
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Because the grammar is a recursive
definition (cf statement), both the
parser and code generator will
involve recursive routines
(methods).
Review
• We have looked at the basic structure of a compiler:
q
q
Lexical analysis: the identification of tokens.
Syntax analysis (parsing): the identification of a program’s
structure.
q
The creation of a ‘parse tree’.
q
Generation of code from the tree.
• The parsing process is driven by the grammar of the
language.
• Correctness checking normally also involves some semantic
checking.
q
Checking that variables are declared.
q
Checking type compatibility in assignments.
q
These are largely ignored in the Jack compiler.
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
CO557: Parsing II
David Barnes
Chapter 10
Compiling I
These slides support chapter 10 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parser design (sneak preview)
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
Parser
class CompilationEngine {
compileStatements() {
// code for compiling statements
}
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
compileIfStatement() {
// code for compiling an if statement
}
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
compileWhileStatement() {
// code for compiling an while statement
}
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
...
The parser consists of a set of
compilexxx methods;
compileTerm() {
// code for compiling a term
}
}
each compilexxx method
implements the right hand side of
the grammar rule describing xxx
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Actually, better to keep the parsing
concept separate from the code
generation, for the sake of generality.
So, I prefer, e.g.,
parseWhileStatement
in the Parser.
Parser design (sneak preview)
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
Parser
class CompilationEngine {
compileStatements() {
// code for compiling statements
}
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
compileIfStatement() {
// code for compiling an if statement
}
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
compileWhileStatement() {
// code for compiling an while statement
}
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
...
The parser consists of a set of
compilexxx methods;
compileTerm() {
// code for compiling a term
}
}
each compilexxx method
implements the right hand side of
the grammar rule describing xxx
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Actually, better to keep the parsing
concept separate from the code
generation, for the sake of generality.
So, I prefer, e.g.,
parseWhileStatement
in the Parser.
Parsing process
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
Parsing process
• Follow the right-hand side of the rule,
and parse the input accordingly
• If the right-hand side specifies a non-terminal
rule xxx, call compilexxx
• Do this recursively.
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
Parsing process
• Follow the right-hand side of the rule,
and parse the input accordingly
• If the right-hand side specifies a non-terminal
rule xxx, call compilexxx
• Do this recursively.
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
Example:
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
Parsing process
• Follow the right-hand side of the rule,
and parse the input accordingly
• If the right-hand side specifies a non-terminal
rule xxx, call compilexxx
• Do this recursively.
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
Example:
Let us assume that we read while,
so we know that we have to call the method
compileWhileStatement
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
parser output
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
<whileStatement>
parser output
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
<whileStatement>
<keyword> while </keyword>
parser output
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
<whileStatement>
<keyword> while </keyword>
parser output
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
<whileStatement>
<keyword> while </keyword>
<symbol> ( </symbol>
parser output
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
<whileStatement>
<keyword> while </keyword>
<symbol> ( </symbol>
parser output
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
<whileStatement>
<keyword> while </keyword>
<symbol> ( </symbol>
<expression>
parser output
compileExpression
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
<whileStatement>
<keyword> while </keyword>
<symbol> ( </symbol>
<expression>
<term>
parser output
compileExpression
compileTerm
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
op: '+' | '-' | '=' | '>' | '<'
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
<symbol> = </symbol>
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
<symbol> = </symbol>
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
compileExpression
<symbol> = </symbol>
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
compileExpression
<symbol> = </symbol>
<expression>
compileTerm
<term> <identifier> count </identifier> </term>
<symbol> + </symbol>
compileTerm
<term> <intConstant> 1 </intConstant> </term>
</expression>
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
compileExpression
<symbol> = </symbol>
<expression>
compileTerm
<term> <identifier> count </identifier> </term>
<symbol> + </symbol>
compileTerm
<term> <intConstant> 1 </intConstant> </term>
</expression>
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
compileExpression
<symbol> = </symbol>
<expression>
compileTerm
<term> <identifier> count </identifier> </term>
<symbol> + </symbol>
compileTerm
<term> <intConstant> 1 </intConstant> </term>
</expression>
<symbol> ; </symbol>
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
compileExpression
<symbol> = </symbol>
<expression>
compileTerm
<term> <identifier> count </identifier> </term>
<symbol> + </symbol>
compileTerm
<term> <intConstant> 1 </intConstant> </term>
</expression>
<symbol> ; </symbol>
input
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
compileExpression
<symbol> = </symbol>
<expression>
compileTerm
<term> <identifier> count </identifier> </term>
<symbol> + </symbol>
compileTerm
<term> <intConstant> 1 </intConstant> </term>
</expression>
<symbol> ; </symbol>
</letStatement>
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
compileExpression
<symbol> = </symbol>
<expression>
compileTerm
<term> <identifier> count </identifier> </term>
<symbol> + </symbol>
compileTerm
<term> <intConstant> 1 </intConstant> </term>
</expression>
<symbol> ; </symbol>
</letStatement>
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
compileExpression
<symbol> = </symbol>
<expression>
compileTerm
<term> <identifier> count </identifier> </term>
<symbol> + </symbol>
compileTerm
<term> <intConstant> 1 </intConstant> </term>
</expression>
<symbol> ; </symbol>
</letStatement>
</statements>
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
compileExpression
<symbol> = </symbol>
<expression>
compileTerm
<term> <identifier> count </identifier> </term>
<symbol> + </symbol>
compileTerm
<term> <intConstant> 1 </intConstant> </term>
</expression>
<symbol> ; </symbol>
</letStatement>
</statements>
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
compileExpression
<symbol> = </symbol>
<expression>
compileTerm
<term> <identifier> count </identifier> </term>
<symbol> + </symbol>
compileTerm
<term> <intConstant> 1 </intConstant> </term>
</expression>
<symbol> ; </symbol>
</letStatement>
</statements>
<symbol> } </symbol>
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
compileWhileStatement
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
<whileStatement>
parser output
<keyword> while </keyword>
<symbol> ( </symbol>
compileExpression
<expression>
compileTerm
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
compileTerm
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
compileStatements
<statements>
compileLetStatement
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
compileExpression
<symbol> = </symbol>
<expression>
compileTerm
<term> <identifier> count </identifier> </term>
<symbol> + </symbol>
compileTerm
<term> <intConstant> 1 </intConstant> </term>
</expression>
<symbol> ; </symbol>
</letStatement>
</statements>
<symbol> } </symbol>
</whileStatement>
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parsing process
statement: ifStatement |
whileStatement |
letStatement
grammar
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
input
<whileStatement>
<keyword> while </keyword>
<symbol> ( </symbol>
<expression>
<term>
<identifier> count </identifier>
</term>
<symbol> < </symbol>
<term>
<intConstant> 100 </intConstant>
</term>
</expression>
<symbol> ) </symbol>
<symbol> { </symbol>
<statements>
<letStatement>
<keyword> let </keyword>
<identifier> count </identifier>
<symbol> = </symbol>
parser output
<expression>
<term> <identifier> count </identifier> </term>
<symbol> + </symbol>
<term> <intConstant> 1 </intConstant> </term>
</expression>
<symbol> ; </symbol>
</letStatement>
</statements>
<symbol> } </symbol>
</whileStatement>
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parser design
Grammar
Parser
statement: ifStatement |
whileStatement |
letStatement
class CompilationEngine {
compileStatements() {
// code for compiling statements
}
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
compileIfStatement() {
// code for compiling an if statement
}
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
varName: a string not beg. with a digit
compileWhileStatement() {
// code for compiling an while statement
}
constant: a decimal number
...
term: varName | constant
op: '+' | '-' | '=' | '>' | '<'
Parser’s design:
compileTerm() {
// code for compiling a term
}
}
• A set of compilexxx methods;
• each compilexxx method implements the right hand side
of the grammar rule describing xxx
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Parser design
Grammar
Parsing process
statement: ifStatement |
whileStatement |
letStatement
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
class CompilationEngine {
...
compileWhileStatement() {
eat('while’); code to handle 'while' ;
eat('('); code to handle '(' ;
compileExpression();
eat(')'); code to handle ')';
...
varName: a string not beg. with a digit
constant: a decimal number
eat(string) {
op: '+' | '-' | '=' | '>' | '<'
if (currentToken <> string)
error...
else
advance...
}
• The code of each compilexxx method follows the right-hand side of the rule xxx
• Each compilexxx method is responsible for advancing and handling its own part of the input.
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
LL grammar
Grammar
statement: ifStatement |
whileStatement |
letStatement
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
• LL grammar: can be parsed by a
recursive descent parser without
backtracking
• LL(k) parser: a parser that needs to
look ahead at most k tokens in order
to determine which rule is applicable
• The grammar that we saw so far is
LL(1).
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Essentially, no left-recursive rules,
such as:
expr ::= expr op term ;
Grammar notation
statement: ifStatement |
whileStatement |
letStatement
statements: statement*
ifStatement: 'if' '(' expression ')’
'{' statements '}’
whileStatement: 'while' '(' expression ')’
'{' statements '}’
letStatement: 'let' varName '=' expression ';'
expression: term (op term)?
term: varName | constant
varName: a string not beg. with a digit
constant: a decimal number
op: '+' | '-' | '=' | '>' | '<'
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
I sometimes use { } for 0-or-more
grouping of multiple T/NT symbols.
Writing parseX/compileX routines: Assessement hints!
• Driven by the nature of the rhs of a grammar rule.
X: terminal
NB: Failing to match does
not mean there is an error.
There might be an
alternative to consider at a
higher-level non terminal.
boolean parseX()
{
if(currentToken matches terminal) {
get next token;
return true;
}
else {
return false;
}
}
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Writing parseX/compileX routines
• Driven by the nature of the rhs of a grammar rule.
X: terminal1 | terminal2
boolean parseX()
{
if(currentToken matches terminal1) {
get next token;
return true;
}
else if(currentToken matches terminal2) {
get next token;
return true;
}
else {
return false;
}
}
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Writing parseX/compileX routines
• Driven by the nature of the rhs of a grammar rule.
X: nt1 | nt2
boolean parseX()
{
if(parseNT1()) {
return true;
}
else if(parseNT2()) {
return true;
}
else {
return false;
}
}
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Writing parseX/compileX routines
• Driven by the nature of the rhs of a grammar rule.
X: nt1 ( terminal nt2 )?
boolean parseX()
{
if(parseNT1()) {
if(currentToken matches terminal) {
get next token;
if(!parseNT2()) {
error – missing nt;
}
}
return true;
}
else {
return false;
}
}
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Writing parseX/compileX routines
• Driven by the nature of the rhs of a grammar rule.
X: nt1 ( terminal nt2 )*
boolean parseX()
{
if(parseNT1()) {
while(currentToken matches terminal) {
get next token;
if(!parseNT2()) {
error – missing nt;
}
}
return true;
}
else {
return false;
}
}
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack grammar
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack grammar: program structure
A Jack program is a collection of classes, each appearing in a separate
file, and each compiled separately. Each class is structured as follows:
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack grammar: program structure
A Jack program is a collection of classes, each appearing in a separate
file, and each compiled separately. Each class is structured as follows:
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack grammar: program structure
A Jack program is a collection of classes, each appearing in a separate
file, and each compiled separately. Each class is structured as follows:
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack grammar: program structure
A Jack program is a collection of classes, each appearing in a separate
file, and each compiled separately. Each class is structured as follows:
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack grammar: program structure
A Jack program is a collection of classes, each appearing in a separate
file, and each compiled separately. Each class is structured as follows:
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack grammar: statements
A Jack program includes statements, as follows:
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack grammar: statements
A Jack program includes statements, as follows:
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack grammar: expressions
A Jack program includes expressions, as follows:
Alternative:
expression: term (op expression)?
NB: the grammar does not capture normally
expected operator precedences.
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Jack grammar: expressions
A Jack program includes expressions, as follows:
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
End note: parsing
Parser’s design
• A set of parsexxx or compilexxx
methods,
structured according to the
grammar rules defining xxx
• Each method outputs some of
the parse tree (XML), and
advances the input
• The parsing logic of each
method follows the right-hand
side of the rule that it
implements.
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
End note: parsing expressions
Parser’s design
• A set of compilexxx methods,
structured according to the
grammar rules defining xxx
• Each method outputs some of
the parse tree (XML), and
advances the input
• The parsing logic of each
method follows the right-hand
side of the rule that it
implements.
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
End note: parsing expressions
When the current token is a
varName (some identifier), it
can be the first token in any
one of these possibilities:
To resolve which possibility we are in,
the parser should “look ahead”:
q save the current token, and
q advance to get the next one.
foo
foo[expression]
foo.bar(expressionList)
Foo.bar(expressionList)
This is the only case in the Jack
grammar in which the language
becomes LL(2) rather than LL(1).
bar(expressionList)
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
Review
• We have looked at some of the practicalities of the parsing
process.
q
A parsing routing for each non-terminal symbol.
q
Use of ‘lookahead’ to determine the next applicable rule.
• We have looked at the notation used to define grammars.
• We have looked at how to use the notation within a rule to
structure the code to parse it.
Nand to Tetris / www.nand2tetris.org / Chapter 10 / Copyright © Noam Nisan and Shimon Schocken
CO557: Code generation I
David Barnes
Chapter 11
Compiling II
These slides support chapter 11 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiler development roadmap
Objective: developing a full-scale compiler
Methodology:
• Adding code generation capabilities.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Program compilation
class Point {
field int x, y;
static int pointCount;
class
declaration
constructor Point new(int ax, int ay) {}
method int getx() {}
method int gety() {}
function int getPointCount() {}
subroutines:
method Point plus(Point other) {}
q
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx)+ (dy*dy));
q
q
constructors
methods
functions
}
method void print() {}
}
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Program compilation
class Point {
field int x, y;
static int pointCount;
constructor Point new(int ax, int ay) {}
method int getx() {}
method int gety() {}
function int getPointCount() {}
Compilation
• class-level code
• subroutine-level code
q
constructors
q
methods
q
functions
method Point plus(Point other) {}
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx)+ (dy*dy));
}
method void print() {}
}
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compilation challenges
• Handling variables
• Handling expressions
• Handling flow of control
• Handling objects
• Handling arrays
The challenge: expressing the above semantics in the VM language.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Variables
High-level (Jack) code
class Foo {
VM code (pseudo)
...
field int a, b, c;
static int x, y;
...
...
push a2
method int bar(int a1; int a2)
{
// let c = a2 + (x – v3)
compiler
var int v1, v2, v3;
...
let c = a2 + (x – v3);
...
}
...
push x
push v3
sub
VM code
add
...
pop c
...
push argument 1
push static 0
push local 2
}
sub
In order to generate VM code,
the compiler must know:
• Whether each variable is a
field, static, local, or argument
add
pop this 2
...
• Whether each variable is the
first, second, third... variable of its kind
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Variables
High-level (Jack) code
class Point {
field int x, y;
static int pointCount;
Variable properties:
q
name (identifier)
q
type (int, char, boolean, class name)
q
kind (field, static, local, argument)
q
index (0, 1, 2, ...)
q
scope (class level, subroutine level)
...
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx)+ (dy*dy));
}
...
}
Variable properties:
• Needed for code generation
• Can be recorded and managed
using a symbol table
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Jack does not need scope to
be represented separately.
Symbol tables: construction
High-level (Jack) code
class-level
symbol table
class Point {
field int x, y;
static int pointCount;
(field, static)
...
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx)+ (dy*dy));
}
...
}
(4,6)
5
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Symbol tables: construction
High-level (Jack) code
class-level
symbol table
class Point {
field int x, y;
static int pointCount;
(field, static)
...
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx)+ (dy*dy));
subroutine-level
symbol table
(argument, local)
}
...
}
In methods only (not in constructors and functions):
(4,6)
• in
addition to the explicit arguments, there is always
an
5 implicit argument:
• argument 0 is always named this, and its type is
always set to the class name
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Symbol tables: construction
High-level (Jack) code
class Point {
field int x, y;
static int pointCount;
...
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx)+ (dy*dy));
}
...
}
Handling variable declarations:
•
(4,6)
5 , static, argument, local),
Each time the compiler detects a variable declaration (field
it adds an entry to the symbol table
• The entry records the variable’s properties.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Symbol tables: usage
High-level (Jack) code
class Point {
field int x, y;
static int pointCount;
...
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx)+ (dy*dy));
}
...
}
(4,6)
Handling variables that appear in statements and expressions:
5
• Each time the compiler detects a variable in some statement
or expression,
it first looks up the variable in the subroutine-level symbol table
• If not found there, it looks it up in the class-level symbol table.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Symbol tables: usage
High-level (Jack) code
class Point {
field int x, y;
static int pointCount;
...
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx)+ (dy*dy));
}
...
look-up
}
VM code
source code example:
...
let y = y + dy;
...
compiler
push this 1
// y
push local 1
// dy
add
pop this 1
// y
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
NB: The right-hand side is translated
first, then the result stored into the
variable on the left-hand side.
Handling variables’ life cycles
Static variables:
Seen by all the class subroutines;
must exist throughout the program’s
execution
High-level (Jack) code
class Point {
field int x, y;
static int pointCount;
Field variables:
Each instance will have its own
set.
...
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx)+ (dy*dy));
Local variables:
During run-time, each time a
subroutine is invoked, it must get a
fresh set of local variables; each time
a subroutine returns, its local variables
must be recycled
}
...
}
Argument variables:
Same as local variables
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
End note: handling nested scoping
class foo { // class level
variable declarations
method bar () { // method level
variable declarations
... { // scope 1 level
variable declarations
... { // scope 2 level
variable declarations
...
}
• Some high-level languages (not
Jack) feature unlimited nested
variable scoping
}
}
}
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
End note: handling nested scoping
class foo { // class level
variable declarations
method bar () { // method level
variable declarations
• Some high-level languages (not
Jack) feature unlimited nested
variable scoping
... { // scope 1 level
variable declarations
... { // scope 2 level
variable declarations
...
}
• Can be handled using a linked list of
symbol tables
}
}
}
symbol
tables
...
scope 2 level
scope 1 level
method level
class level
symbol
table
symbol
table
symbol
table
symbol
table
Variable lookup: start in the first table in the list:
if not found, look up the next table, and so on.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compilation challenges
• Handling variables
• Handling expressions
• Handling flow of control
• Handling objects
• Handling arrays
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Parse tree
prefix
infix
postfix
* a + b c
a * (b + c)
a b c + *
functional
human oriented
stack oriented
*(a,+(b,c))
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Generating code for expressions: a two-stage approach
stack-machine code
source code
x + g(2,y,-z) - 5
parse
tree
code
generation
push x
push 2
push y
push z
(infix)
call g
+
push 5
-
(postfix)
When executed, the generated code ends up leaving
the value of the expression at the top of the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Walk the tree from root to
leaves, generating code from
the leaves to the root.
Generating code for expressions: a one-stage approach
codeWrite(exp):
source code
x + g(2,y,-z) * 5
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Generating code for expressions: a one-pass approach
codeWrite(exp):
source code
x + g(2,y,-z) * 5
NB: Typo * instead of -
stack-machine code
if exp is a number n:
output “push n”
if exp is a variable var:
output “push var”
resulting
code
push x
push 2
push y
if exp is “exp1 op exp2”:
codeWrite(exp1),
remember op,
codeWrite(exp2),
output “op”
push z
if exp is “op exp”:
remember op,
codeWrite(exp),
output “op”
push 5
if exp is “f (exp1, exp2, ...)”:
remember f,
codeWrite(exp1),
codeWrite(exp2), ...,
output “call f ”
call g
+
*
When executed, the generated code ends up leaving
the value of the expression at the top of the stack.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Generating code for expressions: a two-pass approach
source code
x + g(2,y,-z) - 5
parse
tree
Walk the tree from root to
leaves, generating code from
the leaves to the root.
(infix)
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Generating code for expressions: walking a parse tree
stack-machine code
walk(node):
source code
x + g(2,y,-z) * 5
NB: Typo * instead of -
if node is leaf num:
output “push num”
parse
tree
if node is leaf var:
output “push var”
if node is “lhs op rhs”:
walk(lhs),
walk(rhs),
output “op”
if node is “op operand”:
walk(operand),
output “op”
if node is “f (n1, n2, ...)”:
walk(n1),
walk(n2), ...,
output “call f ”
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
resulting
code
push x
push 2
push y
push z
call g
+
push 5
*
End note: operator priority/precedence
• The Jack language definition specifies no operator priority;
• To simplify the compiler writing, we assume left-to-right priority:
push a
let x = a + b * c;
compiler
push b
+
push c
*
pop x
The Jack language definition specifies that expressions in parentheses are evaluated first:
push a
let x = a + (b * c);
compiler
push b
push c
*
+
pop x
This is a really bad idea!
General comment:
The Jack language designers decided to leave the question of how to
handle operator order priority up to the compiler’s implementation.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compilation challenges
• Handling variables
• Handling expressions
• Handling flow of control
• Handling objects
• Handling arrays
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
The challenge
high-level code
let low = 0;
let high = x;
while ((high – low) > epsilon) {
let mid = (high + low) / 2;
if ((mid * mid) > x) {
high = mid;
}
else {
let low = mid;
}
}
return low;
VM code, using:
translate
to:
• goto
• if-goto
• label
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling if statements
VM code
source code
compiled (expression)
if (expression)
statements1
else
statements2
...
not
compiler
if-goto L1
compiled (statements1)
goto L2
label L1
compiled (statements2)
label L2
...
the labels are generated
by the compiler
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
NB: In the translation, the condition
is inverted to avoid jumping over a
jump if the condition is true.
Compiling while statements
VM code
source code
while (expression)
statements
...
compiler
label L1
compiled (expression)
not
if-goto L2
compiled (statements)
goto L1
label L2
...
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Review
high-level code
let low = 0;
let high = x;
while ((high – low) > epsilon) {
let mid = (high + low) / 2;
if ((mid * mid) > x) {
high = mid;
}
else {
let low = mid;
}
}
return low;
Our compiler (front-end) knows
how to handle
• Variables
• Expressions
• Flow of control
Our compiler (back-end) knows
how to handle
• Functions
• Function call-and-return
• Memory allocation
Conclusion:
We can write a compiler for a
simple procedural language!
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Objects and arrays remain
to be dealt with.
CO557: Code generation II
David Barnes
Chapter 11
Compiling II
These slides support chapter 11 of the book
The Elements of Computing Systems
By Noam Nisan and Shimon Schocken
MIT Press
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compilation challenges
• Handling variables
• Handling expressions
• Handling flow of control
• Handling objects
• Handling arrays
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Handling variables: the big picture
/** Represents a Point. */
class Point {
field int x, y;
static int pointCount;
/** Constructs a new point */
constructor Point new(int ax,
int
ay)
{
let x = ax;
let y = ay;
let pointCount =
pointCount + 1;
return this;
}
// ... more Point methods
high-level view
VM
translator
compiler
low-level view
intermediate-level view
• High-level OO programs operate on high-level, symbolic variables
• Mid-level VM programs operate on virtual memory segments
• Low-level machine programs operate directly on the RAM
High-level
The compilation challenge: bridging the gaps.
view
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Handling local and argument variables (review)
Compilation challenge:
• How to represent local and argument variables
using the host RAM
• How to initialize and recycle local and argument
variables when methods start / return
Solution
• The compiler maps the high-level local
and argument variables on local 0, 1, ...
and on argument 0, 1, ...
local
and
argument
segments
• The compiler translates high-level operations on
local and argument variables into VM segment-based
operations on local 0,1,... and on argument 0,1,...
• During run-time, the VM implementation initializes
and recycles the local and argument segments, as
needed, using the global stack.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Handling field variables (object data)
class Point {
field int x, y;
static int pointCount;
...
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx)+ (dy*dy));
}
...
local and
argument
variables
}
•
There may be many objects (class instances)
of type Point
•
Each storing by its own set of x,y values
(fields).
•
As long as the program is running,
all these objects must be managed.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Handling field variables (object data)
Abstraction:
• Each object is represented by a bundle of field
variable values (each object has a private copy
of these values)
• When I call a method, say bar.foo(), I want foo
to operate on a specific object, in this case bar
local and
argument
variables
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Handling field variables (object data)
Abstraction:
• Each object is represented by a bundle of field
variable values (each object has a private copy
of these values)
• When I call a method, say bar.foo(), I want foo
to operate on a specific object, in this case bar
Implementation
• Each object is managed as a separate memory
block, stored in a RAM area named heap
local and
argument
variables
• The current object is represented by the
segment this
• Basic compilation strategy
for accessing object data:
q
q
when we want to operate on a particular object,
we set THIS to its base address
The memory blocks that
represent objects are
managed in the heap
High-level code that uses field i of the current
object can be translated into VM code that operates
on this i.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Accessing the RAM using this
Suppose we wish to access
RAM words 8000, 8001, 8002...
8000
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Accessing the RAM using this
Suppose we wish to access
RAM words 8000, 8001, 8002...
VM code
(commands)
Resulting
effect
push 8000
pop pointer 0
sets THIS to 8000
8000
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Accessing the RAM using this
Suppose we wish to access
RAM words 8000, 8001, 8002...
VM code
(commands)
Resulting
effect
8000
push 8000
pop pointer 0
sets THIS to 8000
push/pop this 0
accesses RAM[8000]
push/pop this 1
accesses RAM[8001]
...
...
push/pop this i
accesses RAM[8000+i]
8000
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Accessing the RAM using this
Suppose we wish to access
RAM words 8000, 8001, 8002...
VM code
(commands)
Resulting
effect
8000
push 8000
pop pointer 0
sets THIS to 8000
push/pop this 0
accesses RAM[8000]
push/pop this 1
accesses RAM[8001]
...
...
push/pop this i
accesses RAM[8000+i]
example:
// Sets the second element
// of the memory block
// beginning at 8000 to 17:
8000
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Accessing the RAM using this
Suppose we wish to access
RAM words 8000, 8001, 8002...
VM code
(commands)
Resulting
effect
8000
push 8000
pop pointer 0
sets THIS to 8000
push/pop this 0
accesses RAM[8000]
push/pop this 1
accesses RAM[8001]
...
...
push/pop this i
accesses RAM[8000+i]
example:
// Sets the second element
// of the memory block
// beginning at 8000 to 17:
8000
push 8000
pop pointer 0
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Accessing the RAM using this
Suppose we wish to access
RAM words 8000, 8001, 8002...
VM code
(commands)
Resulting
effect
8000
push 8000
pop pointer 0
sets THIS to 8000
push/pop this 0
accesses RAM[8000]
push/pop this 1
accesses RAM[8001]
...
...
push/pop this i
accesses RAM[8000+i]
Example:
basic technique
for accessing
object data
// Sets the second element
// of the memory block
// beginning at 8000 to 17:
8000
17
17
push 8000
pop pointer 0
push 17
pop this 1
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compilation challenges
• Handling variables
• Handling expressions
• Handling flow of control
• Handling objects
q
Construction
• Compiling “new”
• Compiling constructors
q
Manipulation
• Handling arrays
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object construction: the big picture
some class
...
var Point p1;
...
callee
let p1 = Point.new(2,3);
Point class
...
class Point {
caller
...
constructor Point new(...)
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object construction: the caller’s side
source code
...
var Point p1, p2;
var int d;
0
p1
0
p2
0
d
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object construction: the caller’s side
source code
...
var Point p1, p2;
var int d;
...
let p1 = Point.new(2,3);
...
0
p1
0
p2
0
d
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object construction: the caller’s side
source code
...
var Point p1, p2;
var int d;
...
let p1 = Point.new(2,3);
...
p1
0
p2
0
d
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object construction: the caller’s side
source code
compiled VM (pseudo) code
...
var Point p1, p2;
var int d;
...
let p1 = Point.new(2,3);
let p2 = Point.new(5,7);
...
// var Point p1, p2
// var int d;
name
type
kind
#
p1
Point
local
0
p2
Point
local
1
d
int
local
2
// The compiler updates the subroutine’s symbol table;
// No code is generated.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object construction: the caller’s side
source code
compiled VM (pseudo) code
...
var Point p1, p2;
var int d;
...
let p1 = Point.new(2,3);
let p2 = Point.new(5,7);
...
// var Point p1, p2
// var int d;
// The compiler updates the subroutine’s symbol table.
// No code is generated.
...
// let p1 = Point.new(2,3)
// Subroutine call:
name
type
kind
#
push 2
push 3
call Point.new
p1
Point
local
0
pop p1
p2
Point
local
1
d
int
local
2
Contract: the caller assumes that
the constructor’s code (i)
arranges a memory block to store
the new object, and (ii) returns its
base address to the caller.
// p1 = base address of the new object
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object construction: the caller’s side
source code
compiled VM (pseudo) code
...
var Point p1, p2;
var int d;
...
let p1 = Point.new(2,3);
let p2 = Point.new(5,7);
...
// var Point p1, p2
// var int d;
// The compiler updates the subroutine’s symbol table.
// No code is generated.
...
// let p1 = Point.new(2,3)
// Subroutine call:
name
type
kind
#
push 2
push 3
call Point.new
p1
Point
local
0
pop p1
p2
Point
local
1
d
int
local
2
Contract: the caller assumes that
the constructor’s code (i)
arranges a memory block to store
the new object, and (ii) returns its
base address to the caller.
// p1 = base address of the new object
// let p2 = Point.new(5,7)
// Similar, code omitted.
...
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Resulting impact
source code
...
var Point p1, p2;
var int d;
...
let p1 = Point.new(2,3);
let p2 = Point.new(5,7);
...
• During compile-time,
the compiler maps p1 on local 0,
p2 on local 1, and d on local 2.
• During run-time, the execution of the
constructor’s code effects the creation
of the objects themselves, on the heap.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object construction: the big picture
some class
var Point p1;
...
let p1 = Point.new(2,3);
callee
Point class
caller
class Point {
...
constructor Point new(...)
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object construction: the big picture
Requirements:
• The constructor must create a new object
• Just like any method, the constructor must be able to manipulate the fields of
the current object
• In the case of constructors, the current object is the newly constructed object
Implementation:
callee
The compiled constructor’s code ...
• starts by creating a memory block for
representing the new object (details later)
class Point {
• Next, it sets THIS to the base address
of this block (using pointer)
• From now on, the constructor’s code
can access the object’s fields
using the this segment.
...
constructor Point new(...)
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
NB: The constructor starts off
acting like a static subroutine
but then behaves like an
instance method.
Compiling constructors
caller’s code
Caller’s code: compiled
separately, shown for context
var Point p1;
...
let p1 = Point.new(2,3);
...
/** Represents a Point. */
class Point {
field int x, y;
static int pointCount;
...
/** Constructs a new point */
constructor Point new(int ax,
int ay) {
let x = ax;
let y = ay;
let pointCount = pointCount + 1;
return this;
}
...
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling constructors
caller’s code
compiled constructor's code
var Point p1;
...
let p1 = Point.new(2,3);
...
...
// constructor Point new(int ax, int ay)
// The compiler creates the subroutine’s symbol table.
/** Represents a Point. */
class Point {
field int x, y;
static int pointCount;
...
/** Constructs a new point */
constructor Point new(int ax,
int ay) {
let x = ax;
let y = ay;
let pointCount = pointCount + 1;
return this;
}
...
classlevel
constructorlevel / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Nand to Tetris / www.nand2tetris.org
Compiling constructors
caller’s code
compiled constructor's code
var Point p1;
...
let p1 = Point.new(2,3);
...
...
// constructor Point new(int ax, int ay)
// The compiler creates the subroutine’s symbol table.
/** Represents a Point. */
class Point {
field int x, y;
static int pointCount;
...
/** Constructs a new point */
constructor Point new(int ax,
int ay) {
let x = ax;
let y = ay;
let pointCount = pointCount + 1;
return this;
}
...
// The compiler figures out the size of an object of this
// class (n), and writes code that calls Memory.alloc(n).
// This OS method finds a memory block of the required
// size, and returns its base address.
push 2 // two 16-bit words are required (x and y)
call Memory.alloc 1 // one argument
pop pointer 0 // anchors this at the base address
classlevel
constructorlevel / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Nand to Tetris / www.nand2tetris.org
Compiling constructors
caller’s code
compiled constructor's code
var Point p1;
...
let p1 = Point.new(2,3);
...
...
// constructor Point new(int ax, int ay)
// The compiler creates the subroutine’s symbol table.
/** Represents a Point. */
class Point {
field int x, y;
static int pointCount;
...
/** Constructs a new point */
constructor Point new(int ax,
int ay) {
let x = ax;
let y = ay;
let pointCount = pointCount + 1;
return this;
}
...
// The compiler figures out the size of an object of this
// class (n), and writes code that calls Memory.alloc(n).
// This OS method finds a memory block of the required
// size, and returns its base address.
push 2 // two 16-bit words are required (x and y)
call Memory.alloc 1 // one argument
pop pointer 0 // anchors this at the base address
// let x = ax; let y = ay;
push argument 0
pop this 0
push argument 1
pop this 1
classlevel
constructorlevel / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Nand to Tetris / www.nand2tetris.org
Compiling constructors
caller’s code
compiled constructor's code
var Point p1;
...
let p1 = Point.new(2,3);
...
...
// constructor Point new(int ax, int ay)
// The compiler creates the subroutine’s symbol table.
/** Represents a Point. */
class Point {
field int x, y;
static int pointCount;
...
/** Constructs a new point */
constructor Point new(int ax,
int ay) {
let x = ax;
let y = ay;
let pointCount = pointCount + 1;
return this;
}
...
classlevel
// The compiler figures out the size of an object of this
// class (n), and writes code that calls Memory.alloc(n).
// This OS method finds a memory block of the required
// size, and returns its base address.
push 2 // two 16-bit words are required (x and y)
call Memory.alloc 1 // one argument
pop pointer 0 // anchors this at the base address
// let x = ax; let y = ay;
push argument 0
pop this 0
push argument 1
pop this 1
// let pointCount = pointCount + 1;
push static 0
push constant 1
add
pop static 0
// return this
push pointer 0
return // returns the base address of the new object
constructorlevel / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Nand to Tetris / www.nand2tetris.org
Compiling constructors
caller’s code
var Point p1;
...
let p1 = Point.new(2,3);
...
compiled constructor's code
...
// constructor Point new(int ax, int ay)
// The compiler creates the subroutine’s symbol table.
// The compiler figures out the size of an object of this
// class (n), and writes code that calls Memory.alloc(n).
// This OS method finds a memory block of the required
// size, and returns its base address.
push 2 // two 16-bit words are required (x and y)
call Memory.alloc 1 // one argument
pop pointer 0 // anchors this at the base address
// let x = ax; let y = ay;
push argument 0
pop this 0
push argument 1
pop this 1
// let pointCount = pointCount + 1;
push static 0
push constant 1
add
pop static 0
// return this
push pointer 0
return // returns the base address of the new object
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling constructors
caller’s code
compiled constructor's code
var Point p1;
...
let p1 = Point.new(2,3);
...
compiled
caller’s code
// let p1 = Point.new(2,3)
push constant 2
push constant 3
call Point.new
pop local 0
...
// constructor Point new(int ax, int ay)
// The compiler creates the subroutine’s symbol table.
// The compiler figures out the size of an object of this
// class (n), and writes code that calls Memory.alloc(n).
// This OS method finds a memory block of the required
// size, and returns its base address.
push 2 // two 16-bit words are required (x and y)
call Memory.alloc 1 // one argument
pop pointer 0 // anchors this at the base address
// let x = ax; let y = ay;
push argument 0
pop this 0
push argument 1
pop this 1
// let pointCount = pointCount + 1;
push static 0
push constant 1
add
pop static 0
// return this
push pointer 0
return // returns the base address of the new object
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object construction: the big picture
var Point p1;
...
let p1 = Point.new(2,3);
callee
caller
class Point {
...
constructor Point new(...)
...
}
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compilation challenges
• Handling variables
• Handling expressions
• Handling flow of control
• Handling objects
q
Construction
q
Manipulation
• Handling arrays
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compilation challenges
• Handling variables
• Handling expressions
• Handling flow of control
• Handling objects
q
Construction
q
Manipulation
• Compiling method calls (caller side)
• Compiling methods (callee side)
• Handling arrays
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object manipulation: high-level
Point class
some class
class Point {
...
var Point p1, p2, p3;
var int x, d;
...
let p1 = Point.new(2,3);
let p2 = Point.new(5,7);
...
let x = p1.getx();
let p3 = p1.plus(p2);
let d = p1.distance(p2);
...
field int x, y;
static int pointCount;
constructor Point new(int ax, int ay) {}
method int getx() {}
method int gety() {}
method int getPointCount() {}
method Point plus(Point other) {}
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx)+ (dy*dy));
caller
callee
}
method void print() {}
}
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling method calls
Source code (OO)
Target code (procedural)
... p1.distance(p2) ...
... distance(p1,p2) ...
... p3.getx() ...
... getx(p3) ...
... obj.foo(x1,x2,...) ...
... foo(obj,x1,x2,...) ...
• The target language is procedural
• Therefore, the compiler must generate procedural code
• Solution: when calling a method, the object on which the method is called to
operate is always passed as a first, implicit argument.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling method calls: the general technique
generated VM (pseudo) code
source code
obj.foo(x1,x2,...)
compiler
// obj.foo(x1,x2,...)
// Pushes the object on which the method
// is called to operate (implicit argument),
// then pushes the method arguments,
// then calls the method for its effect.
push obj
push x1
push x2
push ...
call foo
generated VM (pseudo) code
example:
...
...
let d = p1.distance(p2);
...
compiler
push p1
push p2
call distance
pop d
...
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object manipulation: the big picture
Point class
some class
class Point {
...
var Point p1, p2, p3;
var int x, d;
...
let p1 = Point.new(2,3);
let p2 = Point.new(5,7);
...
let x = p1.getx();
let p3 = p1.plus(p2);
let d = p1.distance(p2);
...
field int x, y;
static int pointCount;
constructor Point new(int ax, int ay) {}
method int getx() {}
method int gety() {}
method int getPointCount() {}
method Point plus(Point other) {}
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx) + (dy*dy));
caller
callee
}
method void print() {}
}
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling methods
Methods are designed to operate
on the current object (this):
Point class
class Point {
Therefore, each method’s code
needs access to the object’s fields
field int x, y;
static int pointCount;
How to access the object’s fields:
method int getx() {}
constructor Point new(int ax, int ay) {}
method int gety() {}
• The method’s code can access
the object’s i-th field by
accessing this i
method int getPointCount() {}
method Point plus(Point other) {}
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx) + (dy*dy));
• On entry, the method’s code
must anchor the this segment
on the object’s data, using
pointer
}
method void print() {}
}
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling methods
/** Represents a Point. */
class Point {
field int x, y;
static int pointCount;
...
/** Distance to the other point */
method int distance(Point other) {
var int dx, dy
let dx = x – other.getx();
let dy = y – other.gety();
return Math.sqrt((dx*dx) +
(dy*dy));
}
...
}
classlevel
methodlevel
compiled VM code
...
// method int distance(Point other)
// var int dx,dy
// The compiler constructs the method’s
// symbol table. No code is generated.
// Next, it generates code that associates the
// this memory segment with the object on
// which the method was called to operate.
push argument 0
pop pointer 0
// THIS = argument 0
// let dx = x – other.getx()
push this 0
push argument 1
call Point.getx 1
sub
pop local 0
// let dy = y – other.gety()
// Similar, code omitted.
// return Math.sqrt((dx*dx)+(dy*dy))
push local 0
push local 0
call Math.multiply 2
push local 1
push local 1
call Math.multiply 2
add
call Math.sqrt 1
return
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling methods
...
let d = p1.distance(p2);
...
Caller’s code:
compiled separately,
shown for context
compiled VM code
...
// method int distance(Point other)
// var int dx,dy
// The compiler constructs the method’s
// symbol table. No code is generated.
// Next, it generates code that associates the
// this memory segment with the object on
// which the method was called to operate.
push argument 0
pop pointer 0
// THIS = argument 0
// let dx = x – other.getx()
push this 0
push argument 1
call Point.getx 1
sub
pop local 0
// let dy = y – other.gety()
// Similar, code omitted.
// return Math.sqrt((dx*dx)+(dy*dy))
push local 0
push local 0
call Math.multiply 2
push local 1
push local 1
call Math.multiply 2
add
call Math.sqrt 1
return
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling methods
...
let d = p1.distance(p2);
...
Caller’s code:
compiled separately,
shown for context
compiled caller (pseudo) code
...
push p1
push p2
call Point.distance
pop d
...
compiled VM code
...
// method int distance(Point other)
// var int dx,dy
// The compiler constructs the method’s
// symbol table. No code is generated.
// Next, it generates code that associates the
// this memory segment with the object on
// which the method was called to operate.
push argument 0
pop pointer 0
// THIS = argument 0
// let dx = x – other.getx()
push this 0
push argument 1
call Point.getx 1
sub
pop local 0
// let dy = y – other.gety()
// Similar, code omitted.
// return Math.sqrt((dx*dx)+(dy*dy))
push local 0
push local 0
call Math.multiply 2
push local 1
push local 1
call Math.multiply 2
add
call Math.sqrt 1
return
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling void methods
...
do p1.print();
...
Caller’s code:
compiled separately,
shown for context
/** Represents a Point. */
class Point {
field int x, y;
static int pointCount;
...
/** Prints the point as (x,y) */
method void print() {
...
}
...
}
compiled VM code
...
// method void print()
// The compiler constructs the method’s
// symbol table. No code is generated.
// Next, it generates code that associates the
// this memory segment with the object on
// which the method is called to operate.
push argument 0
pop pointer 0
// THIS = argument 0
...
// Returns a value (all methods must return a value)
push constant 0
return
classlevel
methodlevel
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling void methods
...
do p1.print();
...
Caller’s code:
compiled separately,
shown for context
compiled VM code
...
// method void print()
// The compiler constructs the method’s
// symbol table. No code is generated.
// Next, it generates code that associates the
// this memory segment with the object on
// which the method is called to operate.
push argument 0
pop pointer 0
// THIS = argument 0
...
// Methods must return a value.
push constant 0
return
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling void methods
...
do p1.print();
...
Caller’s code:
compiled separately,
shown for context
compiled caller (pseudo) code
...
push p1
call Point.print
compiled VM code
...
// method void print()
// The compiler constructs the method’s
// symbol table. No code is generated.
// Next, it generates code that associates the
// this memory segment with the object on
// which the method is called to operate.
push argument 0
pop pointer 0
// THIS = argument 0
...
// Methods must return a value.
push constant 0
return
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling void methods
...
do p1.print();
...
Caller’s code:
compiled separately,
shown for context
compiled caller (pseudo) code
...
push p1
call Point.print
// the caller of a void method
// must dump the returned value
compiled VM code
...
// method void print()
// The compiler constructs the method’s
// symbol table. No code is generated.
// Next, it generates code that associates the
// this memory segment with the object on
// which the method is called to operate.
push argument 0
pop pointer 0
// THIS = argument 0
...
// Methods must return a value.
push constant 0
return
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compiling void methods
...
do p1.print();
...
Caller’s code:
compiled separately,
shown for context
compiled caller (pseudo) code
...
push p1
call Point.print
// the caller of a void method
// must dump the returned value
pop temp 0
compiled VM code
...
// method void print()
// The compiler constructs the method’s
// symbol table. No code is generated.
// Next, it generates code that associates the
// this memory segment with the object on
// which the method is called to operate.
push argument 0
pop pointer 0
// THIS = argument 0
...
// Methods must return a value.
push constant 0
return
...
Compiler writers, heads up:
Callee’s contract (compiled code): before terminating,
the callee must return a value
(by convention, void methods return 0)
Caller’s contract (compiled code): after calling a void method,
the caller must dump the topmost stack value
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Object manipulation: the big picture
Point class
some class
class Point {
...
var Point p1, p2, p3;
var int x, d;
...
let p1 = Point.new(2,3);
let p2 = Point.new(5,7);
...
let x = p1.getx();
let p3 = p1.plus(p2);
let d = p1.distance(p2);
...
field int x, y;
static int pointCount;
constructor Point new(int ax, int ay) {}
method int getx() {}
method int gety() {}
method int getPointCount() {}
method Point plus(Point other) {}
method int distance(Point other) {
var int dx, dy;
let dx = x - other.getx();
let dy = y - other.gety();
return Math.sqrt((dx*dx)+ (dy*dy));
caller
callee
}
method void print() {}
}
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compilation challenges
• Handling variables
• Handling expressions
• Handling flow of control
• Handling objects
• Handling arrays
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compilation challenges
• Handling variables
• Handling expressions
• Handling flow of control
• Handling objects
• Handling arrays
q
Array construction
q
Array manipulation
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Array construction
var Array arr;
...
let arr = Array.new(5);
...
0
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Array construction
var Array arr;
...
let arr = Array.new(5);
...
Code generation
• var Array arr:
• generates no code;
only affects the symbol table
• let arr = Array.new(n):
• from the caller’s perspective,
handled exactly like object construction:
pop result into variable’s location.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compilation challenges
• Handling variables
• Handling expressions
• Handling flow of control
• Handling objects
• Handling arrays
q
Array construction
q
Array manipulation
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
this and that (reminder)
Two virtual memory segments that can be
aligned to different RAM addresses
VM use:
this
that
used to represent
the values of the
current object
used to represent
the values of the
current array
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
this and that (reminder)
Two virtual memory segments that can be
aligned to different RAM addresses
this
that
VM use:
used to represent
the values of the
current object
used to represent
the values of the
current array
pointer
(base
address)
THIS
THAT
how to set:
pop pointer 0
(sets THIS)
pop pointer 1
(sets THAT)
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
NB: Why do we have to set
THIS and THAT indirectly via
pointer?
Example: RAM access using that
// RAM[8056] = 17
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Example: RAM access using that
// RAM[8056] = 17
push 8056
pop pointer 1
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Example: RAM access using that
// RAM[8056] = 17
push 8056
pop pointer 1
push 17
pop that 0
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Example: RAM access using that
// RAM[8056] = 17
push constant 8056
pop pointer 1
push constant 17
pop that 0
17
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Example: RAM access using that
// RAM[8056] = 17
push constant 8056
pop pointer 1
push constant 17
pop that 0
However, to access arr[expr] we cannot generate:
push base address of arr
pop pointer 1
push/pop that value-of-expr
push base address of arr
evaluate expr
add
// address arr+expr now on ToS
pop pointer 1
push/pop that 0
17
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Compilation challenges
• Handling variables
• Handling expressions
• Handling flow of control
• Handling objects
• Handling arrays
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Review
• We have looked at the generation of code to handle objects.
• Objects occupy space in the heap: Memory.alloc.
• The fields of an object persist throughout its lifetime.
• Multiple instances of a class mean that multiple copies of its
fields will exist simultaneously.
• The this segment is used to provide access to the fields of
the ‘current’ object: the one on which the current active
method has been invoked.
• When a method is invoked, the caller must push the callee’s
object reference as the first ‘argument’.
• The callee copies argument 0 to pointer 0.
• A constructor call returns the newly-created object reference
as its result.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Review
• Arrays are stored in the heap.
• An array is accessed via the that segment.
• The base address of the that segment is set via pointer 1.
Nand to Tetris / www.nand2tetris.org / Chapter 11 / Copyright © Noam Nisan and Shimon Schocken
Download