0% found this document useful (0 votes)
3 views

lecture 8

Lecture 8 of 'From Nand to Tetris' focuses on the Virtual Machine (VM) language, completing its development and the VM translator. The lecture covers key concepts such as branching, function calls, and the compilation process, illustrating how high-level programs are translated into VM code. It emphasizes the abstraction and implementation of VM commands, including arithmetic, logical operations, and control flow structures.

Uploaded by

forgetdont538
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

lecture 8

Lecture 8 of 'From Nand to Tetris' focuses on the Virtual Machine (VM) language, completing its development and the VM translator. The lecture covers key concepts such as branching, function calls, and the compilation process, illustrating how high-level programs are translated into VM code. It emphasizes the abstraction and implementation of VM commands, including arithmetic, logical operations, and control flow structures.

Uploaded by

forgetdont538
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 104

From Nand to Tetris

Building a Modern Computer from First Principles

Lecture 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, 2021

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 1
Nand to Tetris Roadmap

software hierarchy
abstract
concept abstraction
program high-level abstraction
language
compiler
OS VM code abstraction
VM
machine
translator
language

assembler

abstraction
hardware platform
computer abstraction
computer
ALU, RAM abstraction
chips elementary d
logic gates gates Nan

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 2
Nand to Tetris Roadmap: Part II

software hierarchy
abstract
concept abstraction
program high-level abstraction
language
compiler
OS VM code abstraction
VM
machine
translator
language

assembler

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 3
Nand to Tetris Roadmap: Part II

software hierarchy
abstract
concept abstraction
program high-level abstraction
language
compiler
OS VM code abstraction
VM
machine
translator
language

assembler
Previous lecture
Introduced the VM language and developed a basic VM translator;

This lecture
Complete the VM language and development of the VM translator.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 4
The big picture: Compilation
High-level program VM code

// Returns x * y // Returns x * y
int mult(int x, int y) { function mult
int sum = 0; push constant 0
int n = 1; pop local 0
// sum = sum + x, y times push constant 1
while !(n > y) { pop local 1
sum += x; label WHILE_LOOP Compilation focus (lectures 10 – 11)
n++; push local 1
}
push argument 1 The compiler maps symbolic variables
return sum;
} gt (sum, n, x,...) on virtual memory segment
if-goto END_LOOP
entries (local 0, local 1, argument 0, ...),
push local 0
push argument 0 and generates VM code that operates
add on these segments.
compiler pop local 0
push local 1
push constant 1
(later in the course)
add
pop local 1
goto WHILE_LOOP
label END_LOOP
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 5
The big picture: Compilation
VM code
The VM Language
// Returns x * y
Arithmetic / Logical commands function mult
push constant 0
• add, sub , neg
pop local 0
• eq , gt , lt, and, or , not push constant 1
pop local 1
Push / pop commands
label WHILE_LOOP Virtual machine focus (lectures 7–8)
• push
push local 1
• pop
push argument 1 Understanding and implementing the
gt
Branching commands
if-goto END_LOOP
target VM code
label
push local 0
goto push argument 0
if-goto add
pop local 0
Function commands push local 1
• function push constant 1
• call add
• return pop local 1
goto WHILE_LOOP
label END_LOOP
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 6
Branching (in a nutshell)
VM code
// Returns x * y
function mult
push constant 0
pop local 0
push constant 1
pop local 1 Programs typically include
label WHILE_LOOP branching logic:
push local 1
push argument 1
• Unconditional goto
gt
• Conditional goto
if-goto END_LOOP
push local 0
push argument 0
add
Implementation challenges
pop local 0
How to realize:
push local 1
push constant 1 • Conditions
add
pop local 1 • Goto destinations
goto WHILE_LOOP
label END_LOOP • Goto operations.
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 7
Functions (in a nutshell)
Function bar Function mult
// Some function // Returns x * y
function bar function mult
... push constant 0
// Computes 8 * 5 + 7 pop local 0
push constant 8 push constant 1
Programs typically consist of one ore more:
push constant 5 pop local 1
“methods” Different high-level languages
call mult 2 label WHILE_LOOP
push constant 7 push local 1 “functions” have different terminologies;
add push argument 1
... gt ”subroutines” In the VM language
return if-goto END_LOOP terminology, all these code
caller “procedures” units are called functions
push local 0
push argument 0
add
etc.
pop local 0
push local 1
push constant 1
add
The functions call each other, as shown in
pop local 1 the example.
goto WHILE_LOOP
label END_LOOP
push local 0
return callee

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 8
Functions (in a nutshell)
Function bar Function mult
// Some function // Returns x * y
function bar function mult
... push constant 0
// Computes 8 * 5 + 7 pop local 0
push constant 8
Implementation issues
push constant 1
push constant 5 pop local 1 How to pass arguments from the caller to
call mult 2 label WHILE_LOOP
the callee?
push constant 7 push local 1
add push argument 1 How to switch from executing the caller
... gt to executing the callee?
return if-goto END_LOOP
caller
push local 0 How to pass the return value from the
push argument 0 callee to the caller?
add
pop local 0 How to terminate the callee, and switch
push local 1 back to the caller?
push constant 1
add
pop local 1
goto WHILE_LOOP
label END_LOOP
push local 0
return callee

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 9
Take home lessons

Understanding program execution


• Branching
• Function call-and-return
• Recursion

Behind the scene


• Compilation
• Virtual machine
• Run-time
• Stack processing.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 10
Branching: Abstraction
// Returns x * y VM branching commands
function mult 2
push constant 0
• label
pop local 0 • goto
push constant 1 • if-goto
pop local 1
label WHILE_LOOP
push local 1
push argument 1
gt
if-goto END_LOOP
push local 0
push argument 0
add
pop local 0
push local 1
push constant 1
add
pop local 1
goto WHILE_LOOP
label END_LOOP
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 11
Branching: Abstraction
// Returns x * y VM branching commands
function mult 2
push constant 0
• label
pop local 0 • goto
push constant 1 • if-goto
pop local 1
label WHILE_LOOP
push local 1
Syntax: label label
push argument 1
gt
if-goto END_LOOP Semantics
push local 0 Marks the destination of goto commands.
push argument 0
add
pop local 0
push local 1
push constant 1
add
pop local 1
goto WHILE_LOOP
label END_LOOP
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 12
Branching: Abstraction
// Returns x * y VM branching commands
function mult 2
push constant 0
• label
pop local 0 • goto
push constant 1 • if-goto
pop local 1
label WHILE_LOOP
push local 1
Syntax: goto label
push argument 1
gt
if-goto END_LOOP Semantics
push local 0 Jump to execute the command just after the label.
push argument 0
add
pop local 0
push local 1
push constant 1
add
pop local 1
goto WHILE_LOOP
label END_LOOP
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 13
Branching: Abstraction
// Returns x * y VM branching commands
function mult 2
push constant 0
• label
pop local 0 • goto
push constant 1 • if-goto
pop local 1
label WHILE_LOOP
push local 1 Syntax: if-goto label
push argument 1
gt Semantics
if-goto END_LOOP
push local 0
1. let cond = pop
push argument 0 2. if cond, jump to execute the command just after the label;
add else, execute the next command.
pop local 0
push local 1
push constant 1
add
pop local 1
goto WHILE_LOOP
label END_LOOP
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 14
Branching: Abstraction
// Returns x * y VM branching commands
function mult 2
push constant 0
• label
pop local 0 • goto
push constant 1 • if-goto
pop local 1
label WHILE_LOOP
push local 1 Syntax: if-goto label
push argument 1
gt Semantics
if-goto END_LOOP
push local 0
1. let cond = pop
push argument 0 2. if cond, jump to execute the command just after the label;
add else, execute the next command.
pop local 0
push local 1 Convention: The code writer (typically, a compiler) must write
push constant 1
code that pushes a boolean expression onto the stack before the
add
if-goto command;
pop local 1
goto WHILE_LOOP In this example, the highlighted code implements the
label END_LOOP abstraction: if (local 1 > argument 1) goto END_LOOP
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 15
Branching: Implementation
Abstraction (recap)
label label // label declaration

goto label // jump to execute the command just after the label

if-goto label // let cond = pop


// if cond jump to execute the command just after the label

Implementation
For each VM branching command, we generate machine language instructions that
realize the command on the target platform. Example:
VM code Hack code
... ... The instruction set of every computer features
label LOOP (LOOP) low-level “labeling” and “goto” primitives;
... ...
goto LOOP VM translator Therefore, the translation of the VM branching
@LOOP
... 0;JMP
commands to the machine language of the
... target platform is not difficult.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 16
Lecture plan

Branching
• Abstraction
• Implementation

Function call and return


• Abstraction
• Implementation

VM translator
• Bootstrap
• Conventions
• Architecture
• Project 8

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 17
Functions: Abstraction
caller callee
function bar 4 // Returns arg 0 * arg 1 Typical scenario
... function mult 2
// Computes 3 + 8 * 5 push constant 0 A function (the caller) calls
push constant 3 pop local 0 a function (the callee)
push constant 8 push constant 1 for its effect
push constant 5 pop local 1
call mult 2 label LOOP
add push local 1
... push argument 1
return
gt
if-goto END
bar’s view:
push local 0
stack push argument 0
just before 3 add
calling mult 8 pop local 0
5 push local 1
stack push constant 1
just after 3 add
calling mult 40 pop local 1
goto LOOP
label END
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 18
Functions: Abstraction
caller callee
VM function commands
function bar 4 // Returns arg 0 * arg 1
... • call
function mult 2
// Computes 3 + 8 * 5 push constant 0 • function
push constant 3 pop local 0
push constant 8 push constant 1
• return
push constant 5 pop local 1
call mult 2 label LOOP
add push local 1
... push argument 1
return
gt
if-goto END
bar’s view:
push local 0
stack push argument 0
just before 3 add
calling mult 8 pop local 0
5 push local 1
stack push constant 1
just after 3 add
calling mult 40 pop local 1
goto LOOP
label END
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 19
Functions: Abstraction
caller callee
VM function commands
function bar 4 // Returns arg 0 * arg 1
... • call
function mult 2
// Computes 3 + 8 * 5 push constant 0 • function
push constant 3 pop local 0
push constant 8 push constant 1
• return
push constant 5 pop local 1
call mult 2 Syntax: call functionName nArgs
label LOOP
add push local 1
... push argument 1
Semantics: Calls function functionName
return
gt for its effect, informing that nArgs argument
if-goto END values were pushed onto the stack
bar’s view:
push local 0
stack
Convention: The caller must push nArgs
push argument 0
just before arguments onto the stack before the call
3 add
calling mult 8 command.
pop local 0
5 push local 1
stack push constant 1
just after 3 add
calling mult 40 pop local 1
goto LOOP
label END
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 20
Functions: Abstraction
caller callee
VM function commands
function bar 4 // Returns arg 0 * arg 1
... • call
function mult 2
// Computes 3 + 8 * 5 push constant 0 • function
push constant 3 pop local 0
push constant 8 push constant 1
• return
push constant 5 pop local 1
call mult 2 Syntax: function functionName nVars
label LOOP
add push local 1
... Semantics
push argument 1
return
gt Here starts the declaration of a function
if-goto END that has name functionName and
bar’s view: nVars local variables
push local 0
stack push argument 0
just before 3 add
calling mult 8 pop local 0
5 push local 1 Note: In this example the caller passes
stack push constant 1 2 arguments, and the function has 2 local
just after add variables. This is just a coincidence;
3
calling mult 40 pop local 1
nArgs had nothing to do with nVars.
goto LOOP
label END
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 21
Functions: Abstraction
caller callee
VM function commands
function bar 4 // Returns arg 0 * arg 1
... • call
function mult 2
// Computes 3 + 8 * 5 push constant 0 • function
push constant 3 pop local 0
push constant 8 push constant 1
• return
push constant 5 pop local 1
call mult 2 label LOOP Syntax: return
add push local 1
...
return
push argument 1 Convention: The callee must push a
gt
value onto the stack before a return
if-goto END command
bar’s view:
push local 0
stack push argument 0
just before 3 add Semantics
calling mult 8 pop local 0
5
The return value will replace (in the stack)
push local 1
the argument values that were pushed by the
stack push constant 1 caller before the call;
just after 3 add
calling mult Control will be transferred back to the caller;
40 pop local 1
goto LOOP Execution will resume with the command just
label END after the call.
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 22
Lecture plan

Branching
• Abstraction
• Implementation

Function call and return


• Abstraction
• Implementation

VM translator
• Bootstrap
• Conventions
• Architecture
• Project 8

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 23
Function call and return
caller callee
function Foo.bar 4 // Returns arg 0 * arg 1 Typical function-call-and-return
... function Foo.mult 2 scenario
// Computes 3 + 8 * 5 push constant 0
push constant 3 Function Foo.bar (the caller) calls
pop local 0
push constant 8 function Foo.mult (the callee)
push constant 1
push constant 5 pop local 1
for its effect
call mult 2 ...
add push local 0
... return
return

VM files and VM functions


The full name of a VM function is fileName.functionName
In this example, the caller and the callee happen to be in the same VM file, Foo.vm
In general, they can be in different VM files.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 24
Function call and return
caller callee
function Foo.bar 4 // Returns arg 0 * arg 1 Typical function-call-and-return
... function Foo.mult 2 scenario
// Computes 3 + 8 * 5 push constant 0
push constant 3 Function Foo.bar (the caller) calls
pop local 0
push constant 8 function Foo.mult (the callee)
push constant 1
push constant 5 pop local 1
for its effect
call mult 2 ...
add push local 0
... return
return

Foo.bar’s view
stack
just before 3
the call 8
5

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 25
Function call and return
caller callee
function Foo.bar 4 // Returns arg 0 * arg 1 Typical function-call-and-return
... function Foo.mult 2 scenario
// Computes 3 + 8 * 5 push constant 0
push constant 3 Function Foo.bar (the caller) calls
pop local 0
push constant 8 function Foo.mult (the callee)
push constant 1
push constant 5 pop local 1
for its effect
call mult 2 ...
add push local 0
... return
return

Foo.bar’s view
stack
just before
the call
3
8
Magic!
5
Let’s open
stack
just after 3
the black box
the call 40

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 26
Function call and return
caller callee
function Foo.bar 4 // Returns arg 0 * arg 1 Typical function-call-and-return
... 0 function Foo.mult 2 scenario
// Computes 3 + 8 * 5 1 push constant 0
push constant 3 2
Function Foo.bar (the caller) calls
pop local 0
push constant 8 function Foo.mult (the callee)
3 push constant 1
push constant 5 pop local 1
for its effect
4
call mult 2 ... ...
add 20 push local 0
... 21 return
return

Adding line numbers,


Foo.bar’s view just for reference
stack
just before 3
the call 8
5

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 27
Function call and return
caller callee
function Foo.bar 4 // Returns arg 0 * arg 1 Typical function-call-and-return
... 0 function Foo.mult 2 scenario
// Computes 3 + 8 * 5 1 push constant 0
push constant 3 2
Function Foo.bar (the caller) calls
pop local 0
push constant 8 function Foo.mult (the callee)
3 push constant 1
push constant 5 pop local 1
for its effect
4
call mult 2 ... ...
add 20 push local 0
... 21 return
return

Foo.bar’s view
stack
just before 3
the call 8
5

The caller’s execution


is put on hold

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 28
Function call and return
caller callee
function Foo.bar 4 // Returns arg 0 * arg 1 Typical function-call-and-return
... 0 function Foo.mult 2 scenario
// Computes 3 + 8 * 5 1 push constant 0
push constant 3 2
Function Foo.bar (the caller) calls
pop local 0
push constant 8 function Foo.mult (the callee)
3 push constant 1
push constant 5 pop local 1
for its effect
4
call mult 2 ... ...
add 20 push local 0
... 21 return
return

Foo.bar’s view Foo.mult‘s view


stack
just before 3 after line 0
the call 8 is executed:
5

The caller’s execution


is put on hold

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 29
Function call and return
caller callee
function Foo.bar 4 // Returns arg 0 * arg 1 Typical function-call-and-return
... 0 function Foo.mult 2 scenario
// Computes 3 + 8 * 5 1 push constant 0
push constant 3 2
Function Foo.bar (the caller) calls
pop local 0
push constant 8 function Foo.mult (the callee)
3 push constant 1
push constant 5 pop local 1
for its effect
4
call mult 2 ... ...
add 20 push local 0
... 21 return
return

Foo.bar’s view Foo.mult‘s view


stack
just before 3 after line 0
the call 8 is executed:
5

arguments are passed

The caller’s execution


is put on hold

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 30
Function call and return
caller callee
function Foo.bar 4 // Returns arg 0 * arg 1 Typical function-call-and-return
... 0 function Foo.mult 2 scenario
// Computes 3 + 8 * 5 1 push constant 0
push constant 3 2
Function Foo.bar (the caller) calls
pop local 0
push constant 8 function Foo.mult (the callee)
3 push constant 1
push constant 5 pop local 1
for its effect
4
call mult 2 ... ...
add 20 push local 0
... 21 return
return

Foo.bar’s view Foo.mult‘s view


stack
just before 3 after line 0
the call 8 is executed:
5
The callee’s code
is executed

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 31
Function call and return
caller callee
function Foo.bar 4 // Returns arg 0 * arg 1 Typical function-call-and-return
... 0 function Foo.mult 2 scenario
// Computes 3 + 8 * 5 1 push constant 0
push constant 3 2
Function Foo.bar (the caller) calls
pop local 0
push constant 8 function Foo.mult (the callee)
3 push constant 1
push constant 5 pop local 1
for its effect
4
call mult 2 ... ...
add 20 push local 0
... 21 return
return

Foo.bar’s view Foo.mult‘s view


stack
just before 3 after line 0
the call 8 is executed:
5
The callee’s code
... is executed
after line 20 40
is executed: 40

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 32
Function call and return
caller callee
function Foo.bar 4 // Returns arg 0 * arg 1 Typical function-call-and-return
... 0 function Foo.mult 2 scenario
// Computes 3 + 8 * 5 1 push constant 0
push constant 3 2
Function Foo.bar (the caller) calls
pop local 0
push constant 8 function Foo.mult (the callee)
3 push constant 1
push constant 5 pop local 1
for its effect
4
call mult 2 ... ...
add 20 push local 0
... 21 return
return

Foo.bar’s view Foo.mult‘s view


stack
just before 3 after line 0
the call 8 is executed:
5
stack The callee’s execution
just after ... 40 is terminating
3 after line 21
the call 40 is executed: 40

return value is passed

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 33
Function call and return
caller callee
function Foo.bar 4 // Returns arg 0 * arg 1 Typical function-call-and-return
... 0 function Foo.mult 2 scenario
// Computes 3 + 8 * 5 1 push constant 0
push constant 3 2
Function Foo.bar (the caller) calls
pop local 0
push constant 8 function Foo.mult (the callee)
3 push constant 1
push constant 5 pop local 1
for its effect
4
call mult 2 ... ...
add 20 push local 0
... 21 return
return

Foo.bar’s view Foo.mult‘s view


stack
just before 3 after line 0
the call 8 is executed:
5
stack The callee’s execution
just after ... 40 is terminating
3 after line 21
the call 40 is executed: 40

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 34
Function call and return
caller callee
function Foo.bar 4 // Returns arg 0 * arg 1 Typical function-call-and-return
... 0 function Foo.mult 2 scenario
// Computes 3 + 8 * 5 1 push constant 0
push constant 3 2
Function Foo.bar (the caller) calls
pop local 0
push constant 8 function Foo.mult (the callee)
3 push constant 1
push constant 5 pop local 1
for its effect
4
call mult 2 ... ...
add 20 push local 0
... 21 return
return

Foo.bar’s view
stack
just before 3
the call 8
5 The caller’s execution is resumed;
The next command to be executed:
stack
just after 3 add
the call 40

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 35
Function call and return
Abstraction (recap):
A VM program consists of one or more VM functions;
The functions call each other, for their effect (including recursively);
Each function execution sees its own working stack and memory segments;
Arguments and return values are passed, somehow.

Implementation
We’ll describe the handling of the function-call-and-return commands in two stages:
• The translation process
• The global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 36
Translation
VM code Generated code (pseudo assembly)
caller: function Foo.bar 4 Conventions
...
// Computes 3 + 8 * 5 Each VM function starts with
push constant 3 a function command, and ends
push constant 8
with a return command;
push constant 5
call Foo.mult 2 Each VM function returns a
add
value (void functions return a
... VM translator
return value which is ignored by the
callee: // Computes arg 0 * arg 1 caller). The return value is the
function Foo.mult 2 top value in the callee’s stack.
push constant 0
pop local 0
push constant 1
pop local 1
...
// Returns the result
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 37
Translation
VM code Generated code (pseudo assembly)
caller: function Foo.bar 4 // function Foo.bar 4
... (Foo.bar) // injected function’s entry point label
// Computes 3 + 8 * 5 // assembly code that initializes the function’s 4 local variables
push constant 3
push constant 8
push constant 5
call Foo.mult 2
add
... VM translator
return
callee: // Computes arg 0 * arg 1
function Foo.mult 2
push constant 0
pop local 0
push constant 1
pop local 1
...
// Returns the result
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 38
Translation
Blue: Generated by the
VM code Generated code (pseudo assembly)
basic VM translator
caller: function Foo.bar 4 // function Foo.bar 4 (project 7);
... (Foo.bar) // injected function’s entry point label
// Computes 3 + 8 * 5 // assembly code that initializes the function’s 4 local variables Black: Generated by
push constant 3 // assembly code that handles ..., push constant 3, ..., push constant 5 the completed VM
push constant 8 translator (project 8).
push constant 5
call Foo.mult 2
add
... VM translator
return
callee: // Computes arg 0 * arg 1
function Foo.mult 2
push constant 0
pop local 0
push constant 1
pop local 1
...
// Returns the result
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 39
Translation
Blue: Generated by the
VM code Generated code (pseudo assembly)
basic VM translator
caller: function Foo.bar 4 // function Foo.bar 4 (project 7);
... (Foo.bar) // injected function’s entry point label
// Computes 3 + 8 * 5 // assembly code that initializes the function’s 4 local variables Black: Generated by
push constant 3 // assembly code that handles ..., push constant 3, ..., push constant 5 the completed VM
push constant 8 // call Foo.mult 2 translator (project 8).
push constant 5 // Creates a return address label (Foo.bar$ret.1); Saves the return
call Foo.mult 2 // address and the caller’s segment pointers, and then generates:
add goto Foo.mult // injected branching to the called function
... VM translator (Foo.bar$ret.1) // injected return address label
return
callee: // Computes arg 0 * arg 1
function Foo.mult 2
push constant 0
pop local 0
push constant 1
pop local 1
...
// Returns the result
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 40
Translation
Blue: Generated by the
VM code Generated code (pseudo assembly)
basic VM translator
caller: function Foo.bar 4 // function Foo.bar 4 (project 7);
... (Foo.bar) // injected function’s entry point label
// Computes 3 + 8 * 5 // assembly code that initializes the function’s 4 local variables Black: Generated by
push constant 3 // assembly code that handles ..., push constant 3, ..., push constant 5 the completed VM
push constant 8 // call Foo.mult 2 translator (project 8).
push constant 5 // Creates a return address label (Foo.bar$ret.1); Saves the return
call Foo.mult 2 // address and the caller’s segment pointers, and then generates:
add goto Foo.mult // injected branching to the called function
... VM translator (Foo.bar$ret.1) // injected return address label
return // assembly code that handles add, ...
callee: // Computes arg 0 * arg 1
function Foo.mult 2
push constant 0
pop local 0
push constant 1
pop local 1
...
// Returns the result
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 41
Translation
VM code Generated code (pseudo assembly)
caller: function Foo.bar 4 // function Foo.bar 4
... (Foo.bar) // injected function’s entry point label
// Computes 3 + 8 * 5 // assembly code that initializes the function’s 4 local variables
push constant 3 // assembly code that handles ..., push constant 3, ..., push constant 5
push constant 8 // call Foo.mult 2
push constant 5 // Creates a return address label (Foo.bar$ret.1); Saves the return
call Foo.mult 2 // address and the caller’s segment pointers, and then generates:
add goto Foo.mult // injected branching to the called function
... VM translator (Foo.bar$ret.1) // injected return address label
return // assembly code that handles add, ...
callee: // Computes arg 0 * arg 1 // function Foo.mult 2
function Foo.mult 2 (Foo.mult) // injected function’s entry point label
push constant 0 // assembly code that initializes the function’s 2 local variables
pop local 0
push constant 1
pop local 1
...
// Returns the result
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 42
Translation
VM code Generated code (pseudo assembly)
caller: function Foo.bar 4 // function Foo.bar 4
... (Foo.bar) // injected function’s entry point label
// Computes 3 + 8 * 5 // assembly code that initializes the function’s 4 local variables
push constant 3 // assembly code that handles ..., push constant 3, ..., push constant 5
push constant 8 // call Foo.mult 2
push constant 5 // Creates a return address label (Foo.bar$ret.1); Saves the return
call Foo.mult 2 // address and the caller’s segment pointers, and then generates:
add goto Foo.mult // injected branching to the called function
... VM translator (Foo.bar$ret.1) // injected return address label
return // assembly code that handles add, ...
callee: // Computes arg 0 * arg 1 // function Foo.mult 2
function Foo.mult 2 (Foo.mult) // injected function’s entry point label
push constant 0 // assembly code that initializes the function’s 2 local variables
pop local 0 // assembly code that handles push constant 0 , ..., push local 0
push constant 1
pop local 1
...
// Returns the result
push local 0
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 43
Translation
VM code Generated code (pseudo assembly)
caller: function Foo.bar 4 // function Foo.bar 4
... (Foo.bar) // injected function’s entry point label
// Computes 3 + 8 * 5 // assembly code that initializes the function’s 4 local variables
push constant 3 // assembly code that handles ..., push constant 3, ..., push constant 5
push constant 8 // call Foo.mult 2
push constant 5 // Creates a return address label (Foo.bar$ret.1); Saves the return
call Foo.mult 2 // address and the caller’s segment pointers, and then generates:
add goto Foo.mult // injected branching to the called function
... VM translator (Foo.bar$ret.1) // injected return address label
return // assembly code that handles add, ...
callee: // Computes arg 0 * arg 1 // function Foo.mult 2
function Foo.mult 2 (Foo.mult) // injected function’s entry point label
push constant 0 // assembly code that initializes the function’s 2 local variables
pop local 0 // assembly code that handles push constant 0 , ..., push local 0
push constant 1 // return
pop local 1 // Retrieves the saved return address (which, in this example, happens to be
... // Foo.bar$ret.1), replaces the arguments pushed by the caller with the
// Returns the result // return value (stack’s top element), reinstates the segment pointers of the
push local 0 // caller, and then generates:
return goto Foo.bar$ret.1 // injected branching back to the calling site.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 44
Translation
VM code Generated code (pseudo assembly)
caller: function Foo.bar 4 // function Foo.bar 4 Notes
... (Foo.bar) // injected function’s entry point label
// Computes 3 + 8 * 5 // assembly code that initializes the function’s 4 local variables This pseudocode must be
push constant 3 // assembly code that handles ..., push constant 3, ..., push constant 5 generated in the target
// call Foo.mult 2
push constant 8
// Creates a return address label (Foo.bar$ret.1); Saves the return
platform’s assembly language;
push constant 5
call Foo.mult 2 // address and the caller’s segment pointers, and then generates: When the resulting assembly
goto Foo.mult // injected branching to the called function
add
code will execute, it will
... VM translator (Foo.bar$ret.1) // injected return address label
return // assembly code that handles add, ... realize the semantics implied
callee: // Computes arg 0 * arg 1 // function Foo.mult 2 by the VM code.
function Foo.mult 2 (Foo.mult) // injected function’s entry point label
push constant 0 // assembly code that initializes the function’s 2 local variables
pop local 0 // assembly code that handles push constant 0 , ..., push local 0
push constant 1 // return
pop local 1 // Retrieves the saved return address (which, in this example, happens to be
... // Foo.bar$ret.1), replaces the arguments pushed by the caller with the
// Returns the result // return value (stack’s top element), reinstates the segment pointers of the
push local 0 // caller, and then generates:
return goto Foo.bar$ret.1 // injected branching back to the calling site.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 45
Translation (detailed): call / function / return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 46
Translation (detailed): call / function / return

The caller is running,


doing various things

working stack
of the caller

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 47
Translation (detailed): call / function / return

The caller prepares to call another function;


It pushes 0 or more arguments onto the stack

working stack
of the caller

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 48
Translation (detailed): call / function / return

The caller prepares to call another function;


It pushes 0 or more arguments onto the stack

working stack
of the caller

nArgs

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 49
Translation (detailed): call / function / return

Handling call functionName nArgs


The caller says: We have to:
call functionName nArgs

working stack
of the caller

nArgs

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 50
Translation (detailed): call / function / return

Handling call functionName nArgs


The caller says: We have to:
call functionName nArgs • Save the return address

working stack
of the caller The address to which control
should return when the callee’s
nArgs execution is terminated

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 51
Translation (detailed): call / function / return

Handling call functionName nArgs


The caller says: We have to:
call functionName nArgs • Save the return address

working stack
of the caller The address to which control
should return when the callee’s
nArgs execution is terminated

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 52
Translation (detailed): call / function / return

Handling call functionName nArgs


The caller says: We have to:
call functionName nArgs • Save the return address
• Save the caller’s segment pointers
working stack
of the caller

nArgs

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 53
Translation (detailed): call / function / return

Handling call functionName nArgs


The caller says: We have to:
call functionName nArgs • Save the return address
• Save the caller’s segment pointers
working stack
of the caller

nArgs

Saved “frame”
of the caller

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 54
Translation (detailed): call / function / return

Handling call functionName nArgs


The caller says: We have to:
call functionName nArgs • Save the return address
• Save the caller’s segment pointers
working stack • Reposition ARG (for the callee)
of the caller
• Reposition LCL (for the callee)

nArgs

Saved “frame”
of the caller

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 55
Translation (detailed): call / function / return

Handling call functionName nArgs


The caller says: We have to:
call functionName nArgs • Save the return address
• Save the caller’s segment pointers
working stack • Reposition ARG (for the callee)
of the caller
• Reposition LCL (for the callee)
ARG
nArgs

Saved “frame”
of the caller

SP, LCL
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 56
Translation (detailed): call / function / return

Handling call functionName nArgs


The caller says: We have to:
call functionName nArgs • Save the return address
• Save the caller’s segment pointers
working stack • Reposition ARG (for the callee)
of the caller
• Reposition LCL (for the callee)
ARG
• Go to execute the callee’s code
nArgs

Saved “frame”
of the caller

SP, LCL
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 57
Translation (detailed): call / function / return

Handling call functionName nArgs


The caller says: We have to:
call functionName nArgs • Save the return address
• Save the caller’s segment pointers
working stack • Reposition ARG (for the callee)
of the caller
• Reposition LCL (for the callee)
ARG
• Go to execute the callee’s code
nArgs
Generated code

// call functionName nArgs


Saved “frame” push retAddrLabel // Generates and pushes this label
of the caller
push LCL // Saves the caller’s LCL
push ARG // Saves the caller’s ARG
SP, LCL
the global stack push THIS // Saves the caller’s THIS
push THAT // Saves the caller’s THAT
ARG = SP – 5 – nArgs // Repositions ARG
LCL = SP // Repositions LCL
goto functionName // Transfers control to the callee
(retAddrLabel) // Injects this label into the code

(The VM translator must generate all this pseudocode in assembly)

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 58
Translation (detailed): call / function / return

The callee is entered:


function functionName nVars Handling function functionName nVars
We have to:
working stack
of the caller
ARG
nArgs

Saved “frame”
of the caller

SP, LCL
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 59
Translation (detailed): call / function / return

The callee is entered:


function functionName nVars Handling function functionName nVars
We have to:
working stack • Inject an entry point label into the code
of the caller
• Initialize the local segment of the callee
ARG
nArgs

Saved “frame”
of the caller

SP, LCL
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 60
Translation (detailed): call / function / return

The callee is entered:


function functionName nVars Handling function functionName nVars
We have to:
working stack • Inject an entry point label into the code
of the caller
• Initialize the local segment of the callee
ARG
nArgs

Saved “frame”
of the caller

LCL
nVars

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 61
Translation (detailed): call / function / return

The callee is entered:


function functionName nVars Handling function functionName nVars
We have to:
working stack • Inject an entry point label into the code
of the caller
• Initialize the local segment of the callee
ARG
nArgs
Generated code
// function functionName nVars
Saved “frame” (functionName) // function’s entry point (injected label)
of the caller
// push nVars 0 values (initializes the callee’s local variables)
push 0
LCL
...
nVars
push 0
SP
the global stack
(The VM translator must generate all this pseudocode in assembly)

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 62
Translation (detailed): call / function / return

The callee is entered:


function functionName nVars

ARG

The callee is all set. It has:


• Arguments (passed by the caller)
LCL
• Local variables (all set to 0)
• Working stack (empty)
SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 63
Translation (detailed): call / function / return

The callee executes,


doing various things

ARG

LCL

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 64
Translation (detailed): call / function / return

The callee executes,


doing various things

ARG

LCL

SP the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 65
Translation (detailed): call / function / return

The callee prepares to return:


It pushes a return value

ARG

LCL

SP the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 66
Translation (detailed): call / function / return

The callee prepares to return:


It pushes a return value

ARG

LCL

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 67
Translation (detailed): call / function / return

Handling return:
The callee says: We have to:
return

ARG

LCL

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 68
Translation (detailed): call / function / return

Handling return:
The callee says: We have to:
return 1. Replace the arguments that the caller pushed
with the value returned by the callee

ARG returned value

LCL

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 69
Translation (detailed): call / function / return

Handling return:
The callee says: We have to:
return 1. Replace the arguments that the caller pushed
with the value returned by the callee
2. Recycle the memory used by the callee

ARG returned value

LCL

SP
the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 70
Translation (detailed): call / function / return

Handling return:
The callee says: We have to:
return 1. Replace the arguments that the caller pushed
with the value returned by the callee
2. Recycle the memory used by the callee

ARG returned value


SP

The stack space below the return


value is effectively wiped out

LCL

the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 71
Translation (detailed): call / function / return

Handling return:
The callee says: We have to:
return 1. Replace the arguments that the caller pushed
with the value returned by the callee
2. Recycle the memory used by the callee
3. Restore the caller’s segment pointers
ARG returned value 4. Jump to the return address
SP

LCL

the global stack

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 72
Translation (detailed): call / function / return

Handling return:
The callee says: We have to:
return 1. Replace the arguments that the caller pushed
with the value returned by the callee
2. Recycle the memory used by the callee
3. Restore the caller’s segment pointers
ARG returned value 4. Jump to the return address
SP
Generated code
// The code below creates and uses two temporary variables:
// endFrame and retAddr;
// The pointer notation *addr is used to denote: RAM[addr].
endFrame = LCL // gets the address at the frame’s end
LCL retAddr = *(endFrame – 5) // gets the return address
*ARG = pop() // puts the return value for the caller
SP = ARG + 1 // repositions SP
THAT = *(endFrame – 1) // restores THAT
THIS = *(endFrame – 2) // restores THIS
ARG = *(endFrame – 3) // restores ARG
LCL = *(endFrame – 4) // restores LCL
the global stack goto retAddr // jumps to the return address

(The VM translator must generate all this pseudocode in assembly)


Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 73
Translation (detailed): call / function / return

The caller resumes


its execution
Result: The caller’s world is exactly the same as
before the call, except that the arguments that it
pushed before the call were replaced by the
returned value LCL value returned by the callee.
SP

Any sufficiently advanced technology is indistinguishable from magic.


– Arthur C. Clarke, 1962

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 74
Translation (detailed): call / function / return

The caller resumes


its execution
What if the calling chain consists
of multiple calls?
returned value
foo calls bar, then bar calls baz, etc.
LCL
SP And what about recursion?

Implementation
Follows exactly the same scheme, once for every call-and-return scenario;
The global stack will grow and shrink telescopically: Last in, first out

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 75
Lecture plan

Abstraction
• VM branching commands
• VM function commands

Implementation (conceptual)
• VM branching commands
• VM function commands

Related topics
• Bootstrap
• Conventions
• Architecture
• Project 8

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 76
The big picture: Compilation
myProg folder
High level language conventions
Main.jack
(much more about it in lecture 9):
class Main
function main {. . . }
Jack program: a set of one or more class files, all in the same folder;
method bar {. . . } Jack class: a set of one or more methods, functions (static methods),
}
and constructors;
There must be at least one class file named Main.jack, and this file
Foo.jack must contain at least one method named main;
class Foo
Program’s entry point: Main.main()
constructor new {. . . }
method bar {. . . }
}
OS conventions
(much more about it in lecture 12):
The OS is written in Jack (just like Unix is written in C);
One OS class, Sys, contains a method named init
When the computer boots, it executes Sys.init
Sys.init calls Main.main.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 77
The big picture: Compilation
myProg folder myProg folder myProg folder
Main.jack
Main.vm myProg.asm
class Main
function Main.main (Main.main)
function main {. . . } ... ...
method bar {. . . } (Main.bar)
function Main.bar
} ... ...

JackCompiler myProg VMtranslator myProg


Foo.jack Foo.vm
(Foo.new)
class Foo function Foo.new
... . ..
constructor new {. . . }
method bar {. . . } (Foo.bar)
function Foo.bar
... . ..
}

Each Jack class is a set Each method, function, All the VM functions
of methods, functions, and constructor is translated are translated into a
and constructors into a VM function single assembly file

Program’s entry point: Main.main()

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 78
Bootstrap code
Run-time conventions
The compiled code base includes the program: A set of VM functions, one of which is Main.main
The compiled code base also includes the operating system: Also a set of VM functions, one of
which is Sys.init
Sys.init initializes the operating system, calls Main.main, and enters an infinite loop
The stack is stored in the RAM, starting at address 256

To make this happen:


The assembly code generated by the VM translator should start with the following code:

// Bootstrap code
SP = 256
call Sys.init // (no arguments)

(The VM translator must generate this pseudocode in assembly)

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 79
Standard mapping of the VM on the Hack platform
ROM RAM
0 0 SP
bootstrap
... code 1 LCL
segment pointers,
... 2 ARG temp segment,
... ... registers R13 – R15
OS 15
Managed by the run-time system
code 16
static (the code generated by the VM translator)
...
variables
255
256
global
...
stack
2047
program
2048
code
... heap
16383
16384
memory Managed by the OS
... mapped
24576 I/O (lecture 12)
24577
... ... unused
32767 32767

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 80
Symbols

Naming
conventions,
Read carefully
for project 8.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 81
Lecture plan

Abstraction
• VM branching commands
• VM function commands

Implementation (conceptual)
• VM branching commands
• VM function commands

VM translator
• Bootstrap
• Conventions
• Architecture
• Project 8

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 82
VM translator

drives the
VMTranslator process

Parser CodeWriter

Reads and parses Generates the assembly


a VM command code that realizes the
parsed command

Each module extends the corresponding module developed in project 7,


Adding the implementation of the branching and function commands.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 83
VM translator
Usage: (if the translator is implemented in Java)
$ java VMTranslator source

Where source is either a single fileName.vm, or a folderName containing one or more .vm files;
(The source may contain a file path; the first character of filename must be an uppercase letter)

Output: A single assembly file named source.asm

Action
• Constructs a CodeWriter
• If source is a .vm file:
Constructs a Parser to handle the input file;
For each VM command in the input file:
uses the Parser to parse the command,
uses the CodeWriter to generate assembly code from it
• If source is a folder:
Handles every .vm file in the folder in the manner described above.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 84
VM translator
drives the
process VMTranslator

Parser CodeWriter

Reads and parses Generates the assembly


a VM command code that realizes the
parsed command

The same Parser developed in project 7:


Handles the parsing of a .vm file:
• Skips white space and comments;
• Reads a VM command, parses the command into its lexical components,
and provides convenient access to these components

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 85
Parser

Same API as in project 7;


If your project 7 Parser
did not handle the parsing
of the VM commands:
goto, if-goto, label,
call, function, return,

add this parsing


functionality now.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 86
VM translator: Proposed design

drives the
process VMTranslator

Parser CodeWriter

Reads and parses Generates the assembly


a VM command code that realizes the
parsed command

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 87
CodeWriter

(API continues in the next slide)

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 88
CodeWriter

The generated assembly code must adhere to the symbol naming conventions.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 89
Lecture plan

Abstraction
• VM branching commands
• VM function commands

Implementation (conceptual)
• VM branching commands
• VM function commands

VM translator
• Bootstrap
• Conventions
• Architecture
• Project 8

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 90
The Big Picture

software hierarchy
abstract Writing a
concept abstraction
program high-level
Building a p7 p8
abstraction
language
compiler Building a
OS VM code abstraction
VM
machine
translator
language

Objective: build a VM translator that translates


programs written in the VM language
into programs written in Hack’s
assembly language CPU
or
emulat
Testing: Run the generated code
on the target platform.

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 91
Test programs
ProgramFlow:
q BasicLoop
q FibonacciSeries

FunctionCalls:
q SimpleFunction
q FibonacciElement
q StaticsTest

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 92
Test programs: BasicLoop
ProgramFlow: BasicLoop.vm
u BasicLoop
// Computes the sum 1 + 2 + ... + argument[0],
BasicLoop.vm // and pushes the result onto the stack.
BasicLoopVME.tst push constant 0
BasicLoop.tst pop local 0
BasicLoop.cmp
label LOOP_START
q FibonacciSeries push argument 0
push local 0
FunctionCalls:
add
q SimpleFunction
pop local 0
q FibonacciElement push argument 0
q StaticsTest push constant 1
Tests the handling of
sub
the VM commands:
pop argument 0
label
push argument 0
if-goto LOOP_START if-goto
push local 0

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 93
Test programs
ProgramFlow:
q BasicLoop
q FibonacciSeries

FunctionCalls:
q SimpleFunction
q FibonacciElement
q StaticsTest

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 94
Test programs: FibonacciSeries
FibSeries.vm
ProgramFlow:
// Computes the first argument[0] elements of the Fibonacci series.
q BasicLoop // Puts the elements in the RAM, starting at the address given in argument[1].
u FibonacciSeries push argument 1
FibSeries.vm pop pointer 1
FibSeriesVME.tst push constant 0
FibSeries.tst pop that 0
FibSeries.cmp push constant 1
pop that 1
FunctionCalls: ...
q SimpleFunction label MAIN_LOOP_START
q FibonacciElement push argument 0
q StaticsTest if-goto COMPUTE_ELEMENT
goto END_PROGRAM
A more elaborate test of
label COMPUTE_ELEMENT handling the VM commands:
push that 0 label
push that 1 goto
add if-goto
...
goto MAIN_LOOP_START
label END_PROGRAM

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 95
Test programs
ProgramFlow:
q BasicLoop
q FibonacciSeries

FunctionCalls:
q SimpleFunction
q FibonacciElement
q StaticsTest

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 96
Test programs: SimpleFunction
SimpleFunction.vm
ProgramFlow:
q BasicLoop // Performs a simple (and meaningless) calculation involving local
// and argument values, and returns the result.
q FibonacciSeries
function SimpleFunction.test 2
FunctionCalls: push local 0
u SimpleFunction push local 1
SimpleFunction.vm add
SimpleFunctionVME.tst not
SimpleFunction.tst push argument 0
add
SimpleFunction.cmp
push argument 1
q FibonacciElement
sub
q StaticsTest
return Tests the handling of the VM commands
function
return
Basic test, involving no caller

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 97
Test programs
ProgramFlow:
q BasicLoop
q FibonacciSeries

FunctionCalls:
q SimpleFunction
q FibonacciElement
q StaticsTest

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 98
Test programs: FibonacciElement
Main.vm
ProgramFlow:
// Main.fibonacci: computes the n'th element of the Fibonacci series,
q BasicLoop
// recursively. The n value is supplied by the caller, and stored in
q FibonacciSeries // argument 0.
function Main.fibonacci 0
FunctionCalls:
push argument 0 • Tests that the VM translator can handle more than one VM file
q SimpleFunction
push constant 2 • Tests the handling of function, return, call
u FibonacciElement lt
Main.vm if-goto IF_TRUE
• Tests that the VM translator initializes the memory segments
Sys.vm goto IF_FALSE • Tests that the bootstrap code initializes the stack and calls Sys.init
FibElementVME.tst label IF_TRUE
FibElement.tst push argument 0 Sys.vm
FibElement.cmp return
label IF_FALSE // Sys.init: pushes n onto the stack,
q StaticsTest
// and calls Main.fibonacii to compute
push argument 0
// the n’th Fibonacci element.
push constant 2
sub // (Called by the bootstrap code generated
// by the VM translator ). Normally, Sys.init is used to
call Main.fibonacci 1 call Main.main;
function Sys.init 0
push argument 0 In Project 8 we use Sys.init to
push constant 4
push constant 1 call test functions, as needed.
call Main.fibonacci 1
sub
call Main.fibonacci 1 label WHILE
goto WHILE
add
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 99
Test programs: FibonacciElement
Main.vm
ProgramFlow:
// Main.fibonacci: computes the n'th element of the Fibonacci series,
q BasicLoop
// recursively. The n value is supplied by the caller, and stored in
q FibonacciSeries // argument 0.
function Main.fibonacci 0
FunctionCalls:
push argument 0
q SimpleFunction
push constant 2
u FibonacciElement lt
Usage: $ VMTranslator FibonacciElement (translates a folder)
Main.vm if-goto IF_TRUE (Should generates a single output file: FibonacciElement.asm)
Sys.vm goto IF_FALSE
FibElementVME.tst label IF_TRUE
FibElement.tst push argument 0 Sys.vm
FibElement.cmp return
label IF_FALSE // Sys.init: pushes n onto the stack,
q StaticsTest
// and calls Main.fibonacii to compute
push argument 0
// the n’th Fibonacci element.
push constant 2
sub // (Called by the bootstrap code generated
// by the VM translator ).
call Main.fibonacci 1
function Sys.init 0
push argument 0
push constant 4
push constant 1
call Main.fibonacci 1
sub
call Main.fibonacci 1 label WHILE
goto WHILE
add
return

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 100
Test programs
ProgramFlow:
q BasicLoop
q FibonacciSeries

FunctionCalls:
q SimpleFunction
q FibonacciElement
q StaticsTest

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 101
Test programs: StaticsTest
Class1.vm
ProgramFlow:
// Stores two supplied arguments in
q BasicLoop
// static 0 and static 1
q FibonacciSeries function Class1.set 0 Class2.vm
push argument 0
FunctionCalls: // Stores two supplied arguments in
pop static 0
q SimpleFunction static 0 and static 1
push argument 1
q FibonacciElement function Class2.set 0 Sys.vm
pop static 1
push argument 0
u StaticsTest push constant 0 function Sys.init 0
Class1.vm pop static 0 Class1.set with 6 and 8
// Calls
return
push argumentpush 1constant 6
Class2.vm
pop staticpush 1 constant 8
Sys.vm // Returns (static 0) – (static 1)
push constantcall 0Class1.set 2
StaticsTestVME.tst function Class1.get 0
return pop temp 0 // dumps the return value
StaticsTest.tst push static 0
push static 1 // Calls Class2.set with 23 and 15
StaticsTest.cmp // Returns (static 0) –constant
(static 1)
sub push 23
function Class2.get 0
push constant 15
return
push static call0 Class2.set 2
push static pop1 temp 0 // dumps the return value
sub // Checks the two resulting static segments
Tests the handling of return Same logic
call Class1.get 0
static variables in a
call Class2.get 0
program consisting of
label WHILE
more than one VM file
goto WHILE

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 102
Test programs
ProgramFlow:
q BasicLoop Testing routine for every test program Xxx:
q FibonacciSeries
0. Recommended: Load and run XxxVME.tst on the VM emulator;
FunctionCalls: This script loads the Xxx test program into the VM emulator,
q SimpleFunction allowing you to experiment with its code
q FibonacciElement 1. Use your VM translator to translate Xxx.vm, generating a file
q StaticsTest named Xxx.asm (if the test includes more than one .vm file,
apply your translator to the folder name)
2. Load and run Xxx.tst on the CPU emulator;
This script loads Xxx.asm into the emulator,
executes it, and compares the output to Xxx.cmp

Note: All the files mentioned above are supplied, except for Xxx.asm

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 103
Recap / Next
program folder program folder
(named, say, points) (points) points.asm points.hack
...
Main.jack Main.vm ...
1101010010101011
M=D 1100001101010101
class Main @i 0101010011101100
...
function void main { M=0 1100101111111111
push local 1
var Point p1; (LOOP) 0101110101010011
push const 3
... @i 1100111111010101
add 0101110110101011
} D=M
... 1100100000001011
} @n
compiler VM translator D=D-M assembler 0101110111100010
1111000111010100
@END 0010101000101011
D;JGT 0111000111010111
Point.jack Point.vm @addr 1010101000101011
class Point ... D=M 0101110110101011
@SP 1100100000001011
field int x,y; push arg 2
M=M+1 0101110111100010
... call Math.sqrt 0101110110101011
} ... @i
0101110111100011
D=M
...
...

Jack code “bytecode”


(4,6)
The VM translator developed in projects 7 – 8 5
is the compiler’s backend.
Next: Introducing the Jack language (project 9)
and completing the compiler’s frontend
(projects 10 – 11).

Nand to Tetris / www.nand2tetris.org / Chapter 8 / Copyright © Noam Nisan and Shimon Schocken Slide 104

You might also like