Unit 8.1 Program Control
In this course, there have 2 components in program control:
- Functions: make the basic language can be extended at will.
- Branching: choose different solutions.
More precisely,
✅Branching commands:
- goto label
- if-goto label
- label label
✅Function commands:
- call function
- function function
- return
Unit 8.2 Branching
✅A. Unconditional branching: goto label
Jumps to execute the command just after label.
✅B. Conditional branching: if-goto label
if cond jump to execute the command just after label(Requires pushing the condition to the stack just before the if-goto command).
✅C. label
Implementation: Translate each branching command into assembly instructions that effect the specified operation.
🎉Simple: the assembly language has similar branching commands.
Unit 8.3 Functions: Abstraction
A. Functions in the VM language
The VM language features:
- primitive operations(fixed): add, sub, …
- abstract operations(extensible): multiply, sqrt, …
B. Functions in the VM language: defining
1 | high-level language pesudo VM code final VM code |
C. Functions in the VM language: executing
⭐Caller: the calling function, Callee: the called function.
In the mult function, it has 3 stacks: stack, argument, local to execute the function code.
D. Making the abstraction work: implementation
For each function call during run-time, the implementation has to:
- Pass parameters from the caller to the callee;
- Determine the return address within the caller’s code;
- Save the caller’s return address, stack and memory segments;
- Jump to execute the callee.
For each function return during run-time, the implementation has to:
- Return to the caller the calue computed by the called function;
- Recycle the meory resources used by the called function;
- Reinstate the caller’s stack and memory segments;
- Jump to the return address in the caller’s code.
Unit 8.4 Function Call and Return: Implementation Preview
A. Function execution
- A computer program typically consists of many functions.
- During a given point of time, only a few functions are executing.
- Calling chain: foo -> bar -> sqrt -> …
B. The function’s state
During run-time:
- Each function uses a working stack + memory segments.
- The working stack and some of the segments should be:
- Created when the function starts running,
- Maintained as long as the function is executing,
- Recycled when the function returns.
Once the callee starts running, the state of the caller has to be saved somewhere. When the callee has terminated, we can reinstate the caller’s state and continue it’s execution.
How to maintain the states of all the functions up the calling chain?
✨The answer is stack.
C. Function call and return: call
VM implementation:
- Sets args
- Saves the caller’s frame
- Jumps to execute foo
D. Function call and return: function
VM implementation:
- Sets up the local segment of the called function
- The called function is running, doing something
- When the called function end, it will prepare to return
E. Function call and return: return
VM implementation:
- Copies the return value onto argument 0
- Restores the segment pointers of the caller
- Clears the stack
- Sets SP for the caller
- Jumps to the return address within the caller’s code.
F. The global stack
The global stack is the physical memory.
⭐block: every function’s global stack, include: argument, saved infomation belongs to caller, local, working stack.
Unit 8.5 Function Call and Return: Run-time Simulation
Unit 8.6 Function Call and Return: Implementation
A. Contract: the calling function’s view
- 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 the temp is undefined and some values of my static segment may have changed).
B. Contract: the called function’s view
- Before I start executing, my argument segment has been initialized with the argument values passed by the caller;
- 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(memory segments this, that, pointer and temp are undefined upon entry)
- My working stack is empty
- Before returning, I must push a value onto the stack.
C. The VM implementation view
1 | VM Translator |
Handing call
VM command: call functionName nArgs
(calls the function, informing that nArgs arguments have been pushed onto the stack)
Assembly code(generated by the translator):
Handing function
VM command: function functionName nVars
(here starts a function that has nVars local variables)
Assembly code(generated by the translator):
Handing return
VM command: return
Assembly code(generated by the translator):
Unit 8.7 VM Implementation on the Hack Platform
Booting
VM programming 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 convention:
When the VM implementation starts running, or is reset, it starts executing the argument-less OS function Sys.init; Sys.init then calls Main.main, and enters an infinite loop.
Hardware platform convention:1
2
3// Bootstrap code
SP=256
Call Sys.init
Standard mapping of the VM on the Hack platform
What we need to care about is the content of the following picture:
Special symbols in VM programs
see the book.😁
Unit 8.8 VM Translator: Proposed Implementation
Main
Parser
CodeWriter
Unit 8.9 Building the VM Translator, Part II
Unit 8.9 Project 8: Building VM Translator, Part II
Extend the basic VM translator built in Project 7 into a full-scale VM translator. In particular, add the ability to handle the program flow and function calling commands of the VM language.
Here is the codes:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum CommandType {
C_UNKONWN,
C_ARITHMETIC,
C_PUSH,
C_POP,
C_LABEL,
C_GOTO,
C_IF,
C_FUNCTION,
C_RETURN,
C_CALL,
};
✅ commandtype.h has no difference with the previous version.
1 |
|
✅ parser.h has no difference with the previous version.
1 |
|
🔨 parser.cpp has one difference with the previous version: the function arg2 has been modified.
1 |
|
🔨 codewriter.h has several differences with the previous version: enable VM translator to handle programm flow and functions calling commands.
1 |
|
🔨 codewriter.cpp also has several differences with the previous version:
- modify the name of variables to translate different commands
- implement the program flow and function calling commands
🎈 PS: reserve some comments for debugging.
1 |
|
🔨 codewriter.cpp also has several differences with the previous version:
- compelted the processing for directory
- use doTranslate function to complete work
- provide easy exception support
Unit 8.10 Perspective
- How useful is this VM language? Does it really make the writing of compilers easy?
- Of course. The virtual machine is an extremely powerful and practical idea.
- What about efficiency? Why is C++ more efficient than Java?
- Obviously any two-stage translation model entails additional overhead, and results in more lines of less efficient machine code.
- Why is Java more secure than C++, and what does this has to do with our VM architecture?
- For example, we can inspect the VM code and look for security breaches. It’s much easier to analyze the symantics of VM programs compared to machine language programs, which are far more elaborate and cryptic. Also, let’s not forget that the VM code must be handled by some virtual machine implementation. SO we can design this implementation in a way that creates what is sometimes called a sandbox effect. The idea is that during runtime, executing programs can never reach out of this sandbox and mess up with toys that they are not allowed to manipulate, like the host RAM. And that’s extremely important in a world in which software is routinely downloaded off the internet, to your computer or to your cell phone, without you even knowing this. So in that respect, the VM implementation that runs on your PC, or your cell phone can be viewed not only as an enabing technology, but also a security layer that protects your device from malicious code.