mirror of
https://github.com/soconnor0919/eceg431.git
synced 2025-12-11 06:34:43 -05:00
project08 template files
This commit is contained in:
21
08/FunctionCalls/FibonacciElement/FibonacciElement.tst
Normal file
21
08/FunctionCalls/FibonacciElement/FibonacciElement.tst
Normal file
@@ -0,0 +1,21 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/FunctionCalls/FibonacciElement/FibonacciElement.tst
|
||||
|
||||
// Tests FibonacciElement.asm on the CPU emulator.
|
||||
// FibonacciElement.asm results from translating Main.vm and Sys.vm into
|
||||
// a single assembly program, stored in the file FibonacciElement.asm.
|
||||
|
||||
load FibonacciElement.asm,
|
||||
output-file FibonacciElement.out,
|
||||
compare-to FibonacciElement.cmp,
|
||||
|
||||
repeat 6000 {
|
||||
ticktock;
|
||||
}
|
||||
|
||||
// Outputs the stack pointer and the value at the stack's base.
|
||||
// That's where the implementation should put the return value.
|
||||
output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1;
|
||||
output;
|
||||
21
08/FunctionCalls/FibonacciElement/FibonacciElementVME.tst
Normal file
21
08/FunctionCalls/FibonacciElement/FibonacciElementVME.tst
Normal file
@@ -0,0 +1,21 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/FunctionCalls/FibonacciElement/FibonacciElementVME.tst
|
||||
|
||||
// Tests and illustrates the given Fibonacci element program on the VM emulator.
|
||||
|
||||
load, // loads all the VM files from the current folder
|
||||
output-file FibonacciElement.out,
|
||||
compare-to FibonacciElement.cmp,
|
||||
|
||||
set sp 261,
|
||||
|
||||
repeat 110 {
|
||||
vmstep;
|
||||
}
|
||||
|
||||
// Outputs the stack pointer and the value at the stack's base.
|
||||
// That's where the implementation should put the return value.
|
||||
output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1;
|
||||
output;
|
||||
31
08/FunctionCalls/FibonacciElement/Main.vm
Normal file
31
08/FunctionCalls/FibonacciElement/Main.vm
Normal file
@@ -0,0 +1,31 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/FunctionCalls/FibonacciElement/Main.vm
|
||||
|
||||
// Contains one function: Main.fibonacci.
|
||||
|
||||
// Computes the n'th element of the Fibonacci series, recursively.
|
||||
// n is given in argument[0]. Called by the Sys.init function
|
||||
// (part of the Sys.vm file), which sets argument[0] to an input
|
||||
// value and then calls Main.fibonacci.
|
||||
function Main.fibonacci 0
|
||||
push argument 0
|
||||
push constant 2
|
||||
lt
|
||||
if-goto N_LT_2
|
||||
goto N_GE_2
|
||||
label N_LT_2 // if n < 2 returns n
|
||||
push argument 0
|
||||
return
|
||||
label N_GE_2 // 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
|
||||
18
08/FunctionCalls/FibonacciElement/Sys.vm
Normal file
18
08/FunctionCalls/FibonacciElement/Sys.vm
Normal file
@@ -0,0 +1,18 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/FunctionCalls/FibonacciElement/Sys.vm
|
||||
|
||||
// Containts one function: Sys.init.
|
||||
|
||||
// Pushes a constant n onto the stack, and calls the Main.fibonacii
|
||||
// function, which computes the n'th element of the Fibonacci series.
|
||||
// Note that by convention, the Sys.init function is called "automatically"
|
||||
// by the bootstrap code generated by the VM translator.
|
||||
function Sys.init 0
|
||||
// Computes fibonacci(4)
|
||||
push constant 4
|
||||
// Calls the function, informing that one argument was pushed onto the stack
|
||||
call Main.fibonacci 1
|
||||
label END
|
||||
goto END // loops infinitely
|
||||
194
08/FunctionCalls/NestedCall/NestedCall.html
Normal file
194
08/FunctionCalls/NestedCall/NestedCall.html
Normal file
@@ -0,0 +1,194 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>NestedCall.tst — Nand2Tetris Calling Convention Test</title>
|
||||
<style type="text/css">
|
||||
.code {font-family:"Courier New", Courier, monospace; font-size:90%;}
|
||||
pre {margin-left:2em;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<h3>Synopsis</h3>
|
||||
<b>NestedCall.tst</b> is an intermediate test (in terms of complexity) intended to be used between the SimpleFunction and
|
||||
FibonacciElement tests. It may be useful when SimpleFunction passes but FibonacciElement fails or crashes. NestedCall also
|
||||
tests several requirements of the Function Calling Protocol that are not verified by the other
|
||||
supplied tests. NestedCall can be used with or without the VM bootstrap code.
|
||||
<p>
|
||||
<b>NestedCallVME.tst</b> runs the same test on the VM Emulator.
|
||||
<p>
|
||||
<b>The NestedCall</b> tests and supporting documentation were written by Mark Armbrust.
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<h3>Test Structure</h3>
|
||||
<h4>Startup</h4>
|
||||
NestedCall is implemented entirely within the Sys.vm file. The first function in Sys.vm is
|
||||
Sys.init(). This allows it to be used before the bootstrap code has been added to the VM Translator
|
||||
since there will be no file processing order issues.
|
||||
<p>
|
||||
NestedCall loads Sys.asm, sets up the stack to simulate the bootstrap's call to Sys.init(), then
|
||||
begins execution at the beginning of Sys.asm. If the bootstrap is not present, the program begins
|
||||
running with Sys.init() since it is the first function in Sys.vm.
|
||||
<p>
|
||||
If Sys.asm includes the bootstrap, the bootstrap will (re)initialize the stack and call Sys.init(),
|
||||
so the test should see the same environment either way it gets to Sys.init().
|
||||
|
||||
<h4>Sys.init()</h4>
|
||||
|
||||
<span class="code">THIS</span> and <span class="code">THAT</span> are set to known values so that context save and restore can be tested.
|
||||
<p>
|
||||
Sys.init() calls Sys.main() and stores the return value in <span class="code">temp 1</span>. This tests call to and
|
||||
return from a function with no arguments.
|
||||
|
||||
<h4>Sys.main()</h4>
|
||||
Sys.init() allocates 5 local variables. It sets <span class="code">local 1</span>, <span class="code">local 2</span> and
|
||||
<span class="code">local 3</span>. <span class="code">local 0</span> and <span class="code">local 4</span> are intentionally not set.
|
||||
<p>
|
||||
<span class="code">THIS</span> and <span class="code">THAT</span> are changed so that context save and restore can be tested.
|
||||
<p>
|
||||
Sys.main() calls Sys.add12(123) and stores the return value in <span class="code">temp 0</span>. This tests call to and
|
||||
return from a function with arguments.
|
||||
<p>
|
||||
After Sys.add12() returns, Sys.main() sums <span class="code">local 0</span> through <span class="code">local 4</span> and returns the
|
||||
result. This tests that the local segment was properly allocated on the stack and that the local
|
||||
variables were not overwritten by the call to Sys.main(). It also tests that <span class="code">local 0</span> and
|
||||
<span class="code">local 4</span> were properly initialized to 0.
|
||||
|
||||
<h4>Sys.add12()</h4>
|
||||
|
||||
<span class="code">THIS</span> and <span class="code">THAT</span> are set to known values so that context save and restore can be tested.
|
||||
<p>
|
||||
Returns <span class="code">argument 0</span> plus 12.
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<h3>Test Coverage</h3>
|
||||
|
||||
<p style="margin-left:1em; text-indent:-1em;">
|
||||
Functions with no arguments return to correct RIP (Return Instruction Point) with correct return value on stack.<br>
|
||||
This can fail if the RIP is not correctly pushed on the stack by the calling code, or if the returning
|
||||
code does not store the RIP in a temporary register before overwriting it with the return value.
|
||||
|
||||
<p style="margin-left:1em; text-indent:-1em;">
|
||||
Functions with arguments return to correct RIP with correct return value on stack.<br>
|
||||
This can fail if it is assumed that <span class="code">ARG</span> points to the RIP.
|
||||
|
||||
<p style="margin-left:1em; text-indent:-1em;">
|
||||
Functions with local variables allocate space on the stack for the local variables.<br>
|
||||
This can fail if the function prologue is not written or if the SP is not updated after zeroing
|
||||
the local variables.
|
||||
|
||||
<p style="margin-left:1em; text-indent:-1em;">
|
||||
All local variables are initialized to 0.<br>
|
||||
Common errors are to forget this completely, or for the zeroing loop to be off by one.
|
||||
|
||||
<p style="margin-left:1em; text-indent:-1em;">
|
||||
<span class="code">THIS</span> and <span class="code">THAT</span> are correctly retained across function calls. Looking ahead, in Project 9 you will be asked to write a simple computer game in the high-level Jack language. You can run your game (following compilation) on the supplied VM Emulator. But, if you choose to translate the VM code that the compiler generates using <em>your</em> VM Translator, then code like
|
||||
"<span class="code">push THIS</span>, <span class="code">push THAT</span> ... <span class="code">pop THIS</span>, <span class="code">pop THAT</span>" can cause some interesting failures!
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<h3>Debugging</h3>
|
||||
These comments assume that your VM translator has passed the SimpleFunction test.
|
||||
<p>
|
||||
If <span class="code">RAM[0]</span> is incorrect, you have a stack skew. More data was pushed onto the stack by
|
||||
<span class="code">call</span> than was popped by <span class="code">return</span>, or vice versa. See <i>debugging with
|
||||
breakpoints</i> later in this section.
|
||||
<p>
|
||||
If one or more of <span class="code">RAM[1]</span> through <span class="code">RAM[4]</span> is incorrect, the <span class="code">LCL</span>,
|
||||
<span class="code">ARG</span>, <span class="code">THIS</span> and <span class="code">THAT</span> pointers are not being correctly saved or restored.
|
||||
Most likely problem is when they are being saved; the SimpleFunction test verified that
|
||||
<span class="code">return</span> restored them correctly.
|
||||
<p>
|
||||
If <span class="code">RAM[5]</span> is incorrect there may be a problem with setting up the <span class="code">ARG</span> pointer.
|
||||
<p>
|
||||
If <span class="code">RAM[4]</span> is incorrect and <span class="code">RAM[5]</span> is correct, there may be a problem with
|
||||
allocation or initialization of local variables.
|
||||
|
||||
<h4>Debugging with breakpoints</h4>
|
||||
|
||||
To find tough bugs you can use the "breakpoint" facility in the CPU Emulator (red flag button).
|
||||
You can use breakpoints to have you program stop when it gets to a particular RAM address. For
|
||||
example:<br>
|
||||
 • load the NestedCall.tst file,<br>
|
||||
 • set a PC breakpoint at the ROM address for <span class="code">(Sys.main)</span>,<br>
|
||||
 • hit the run button.<br>
|
||||
When the CPU Emulator stops at the breakpoint you can inspect the RAM to check the stack and pointers values.
|
||||
(If the breakpoint isn't hit, you will need to to single-step debug through
|
||||
your calling code to see why it didn't get there.)
|
||||
<p>
|
||||
Other useful places to set breakpoints are the entry points to the other functions and at the
|
||||
first and final instructions generated for <span class="code">return</span> commands.
|
||||
<p>
|
||||
<a href="NestedCallStack.html">NestedCallStack.html</a> shows the expected stack values at various points
|
||||
during the test.
|
||||
|
||||
<h4>Finding ROM address in your ASM code</h4>
|
||||
It is not easy to find the ROM locations where you want to set breakpoints, because there is no
|
||||
one-to-one correspondence between the ASM file line numbers and the ROM addresses. This is made even more
|
||||
difficult because the supplied CPU Emulator does not display the (LABELS) in its ROM panel.
|
||||
<p>
|
||||
There are two things that you can do to make this easier.
|
||||
<p>
|
||||
<h5>Modify your assembler to generate a listing file.</h5>
|
||||
A listing file shows all the ASM source lines, including comments, as well as the ROM addresses and
|
||||
the values of the labels and the instructions. For example, here is a snippet of a listing file generated by an assembler written by Mark Armbrust:
|
||||
<pre>
|
||||
20 16 @i // i -= 1
|
||||
21 FC88 M=M-1
|
||||
|
||||
22 FC10 D=M // if i > 0
|
||||
23 6 @LOOP
|
||||
24 E301 D;JGT // goto LOOP
|
||||
|
||||
25 (STOP)
|
||||
25 25 @STOP
|
||||
26 EA87 0;JMP
|
||||
|
||||
Data Symbols
|
||||
|
||||
16 D i
|
||||
|
||||
Code Symbols
|
||||
|
||||
6 C LOOP
|
||||
17 C SKIP
|
||||
25 C STOP
|
||||
</pre>
|
||||
For the Nand2Tetris environment, it is most useful to list the ROM addresses and A-instruction
|
||||
values in decimal. In the above snippet, the C-instruction values are
|
||||
listed in hexadecimal.
|
||||
<p>
|
||||
The list file is generated during pass 2 of the Assembler, parallel to generating the .hack file. To
|
||||
make it easier to handle blank and comment only lines, Mark has Parser.commandType() return
|
||||
NO_COMMAND for source lines with no command. Mark also added Parser.sourceLine() that returns the
|
||||
unmodified source line.
|
||||
<p>
|
||||
<h5>Have your VM Translator write the VM source lines as comments in the ASM output.</h5>
|
||||
For example:
|
||||
<pre>
|
||||
// label LOOP
|
||||
(Sys.init$LOOP)
|
||||
// goto LOOP
|
||||
@Sys.init$LOOP
|
||||
0;JMP
|
||||
//
|
||||
// // Sys.main()
|
||||
//
|
||||
// // Sets locals 1, 2 and 3, leaving locals 0 and 4 unchanged to test
|
||||
// // default local initialization to 0. (RAM set to -1 by test setup.)
|
||||
// // Calls Sys.add12(123) and stores return value (135) in temp 0.
|
||||
// // Returns local 0 + local 1 + local 2 + local 3 + local 4 (456) to confirm
|
||||
// // that locals were not mangled by function call.
|
||||
//
|
||||
// function Sys.main 5
|
||||
(Sys.main)
|
||||
@5
|
||||
D=-A
|
||||
($3)
|
||||
@SP
|
||||
</pre>
|
||||
Note that comments in the VM source become double comments. Looking ahead, in Project 11 you will be asked to write a compiler for the Jack language. If your compiler will write the Jack source lines as comments in the
|
||||
generated VM files, this convention will be quite useful.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
69
08/FunctionCalls/NestedCall/NestedCall.tst
Normal file
69
08/FunctionCalls/NestedCall/NestedCall.tst
Normal file
@@ -0,0 +1,69 @@
|
||||
// Tests how the VM implementation handles function-call-and-return,
|
||||
// by executing the functions in Sys.vm.
|
||||
// In particular, loads and runs NestedCall.asm, which results when
|
||||
// the VM translator is applied to the NestedCall folder, which
|
||||
// includes only one VM file: Sys.vm.
|
||||
|
||||
load NestedCall.asm,
|
||||
output-file NestedCall.out,
|
||||
compare-to NestedCall.cmp,
|
||||
|
||||
set RAM[0] 261,
|
||||
set RAM[1] 261,
|
||||
set RAM[2] 256,
|
||||
set RAM[3] -3,
|
||||
set RAM[4] -4,
|
||||
set RAM[5] -1, // test results
|
||||
set RAM[6] -1,
|
||||
set RAM[256] 1234, // fake stack frame from call Sys.init
|
||||
set RAM[257] -1,
|
||||
set RAM[258] -2,
|
||||
set RAM[259] -3,
|
||||
set RAM[260] -4,
|
||||
|
||||
set RAM[261] -1, // Initializes the stack, to check that the local segment
|
||||
set RAM[262] -1, // is initialized to zeros by the 'function' VM command.
|
||||
set RAM[263] -1,
|
||||
set RAM[264] -1,
|
||||
set RAM[265] -1,
|
||||
set RAM[266] -1,
|
||||
set RAM[267] -1,
|
||||
set RAM[268] -1,
|
||||
set RAM[269] -1,
|
||||
set RAM[270] -1,
|
||||
set RAM[271] -1,
|
||||
set RAM[272] -1,
|
||||
set RAM[273] -1,
|
||||
set RAM[274] -1,
|
||||
set RAM[275] -1,
|
||||
set RAM[276] -1,
|
||||
set RAM[277] -1,
|
||||
set RAM[278] -1,
|
||||
set RAM[279] -1,
|
||||
set RAM[280] -1,
|
||||
set RAM[281] -1,
|
||||
set RAM[282] -1,
|
||||
set RAM[283] -1,
|
||||
set RAM[284] -1,
|
||||
set RAM[285] -1,
|
||||
set RAM[286] -1,
|
||||
set RAM[287] -1,
|
||||
set RAM[288] -1,
|
||||
set RAM[289] -1,
|
||||
set RAM[290] -1,
|
||||
set RAM[291] -1,
|
||||
set RAM[292] -1,
|
||||
set RAM[293] -1,
|
||||
set RAM[294] -1,
|
||||
set RAM[295] -1,
|
||||
set RAM[296] -1,
|
||||
set RAM[297] -1,
|
||||
set RAM[298] -1,
|
||||
set RAM[299] -1,
|
||||
|
||||
repeat 4000 {
|
||||
ticktock;
|
||||
}
|
||||
|
||||
output-list RAM[0]%D1.6.1 RAM[1]%D1.6.1 RAM[2]%D1.6.1 RAM[3]%D1.6.1 RAM[4]%D1.6.1 RAM[5]%D1.6.1 RAM[6]%D1.6.1;
|
||||
output;
|
||||
306
08/FunctionCalls/NestedCall/NestedCallStack.html
Normal file
306
08/FunctionCalls/NestedCall/NestedCallStack.html
Normal file
@@ -0,0 +1,306 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>NestedCall.tst — Stack Frames</title>
|
||||
<style type="text/css">
|
||||
.stack {border-collapse:collapse; font-size:80%;}
|
||||
.stack td {padding-left:.25em;padding-right:.25em;white-space:nowrap;}
|
||||
.stack td:first-child {text-align:right;}
|
||||
.stack td:first-child + td {text-align:right;}
|
||||
.stack td:first-child + td + td {text-align:left;}
|
||||
.stack td:first-child + td + td + td {text-align:left;}
|
||||
.stack .reg {border-left:1px solid; border-right:1px solid;}
|
||||
.stack .reg th {border:1px solid;}
|
||||
.stack .stack {border-left:1px solid; border-right:1px solid;}
|
||||
.stack .stack th {border:1px solid;}
|
||||
.stack .tos {border-left:1px solid; border-right:1px solid;border-bottom:1px solid;}
|
||||
.stack .frame {border-left:1px solid; border-right:1px solid;}
|
||||
.stack .frame td:first-child + td {border-left:1px solid;}
|
||||
.stack .frame td:first-child + td + td {border-right:1px solid;}
|
||||
.stack .framet {border-left:1px solid; border-right:1px solid;}
|
||||
.stack .framet td:first-child + td {border-left:1px solid;border-top:1px solid;}
|
||||
.stack .framet td:first-child + td + td {border-right:1px solid;border-top:1px solid;}
|
||||
.stack .bframe {border-left:1px solid; border-right:1px solid;}
|
||||
.stack .bframe td:first-child + td {border-left:2px solid;}
|
||||
.stack .bframe td:first-child + td + td {border-right:2px solid;}
|
||||
.stack .bframet {border-left:1px solid; border-right:1px solid;}
|
||||
.stack .bframet td:first-child + td {border-left:2px solid;border-top:2px solid;}
|
||||
.stack .bframet td:first-child + td + td {border-right:2px solid;border-top:2px solid;}
|
||||
.stack .bframeb {border-left:1px solid; border-right:1px solid;}
|
||||
.stack .bframeb td:first-child + td {border-left:2px solid;border-bottom:2px solid;}
|
||||
.stack .bframeb td:first-child + td + td {border-right:2px solid;border-bottom:2px solid;}
|
||||
.stack .note td {padding-left:.5em;padding-right:.5em;white-space:normal;text-align:justify;}
|
||||
.stack .fid {font-style:italic}
|
||||
.master {width: 10%;}
|
||||
.master td {vertical-align:top;padding-right:.5em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<table class="master">
|
||||
<tr>
|
||||
<td>
|
||||
<table class="stack">
|
||||
<tr><th colspan="4">Bootstrap init</th></tr>
|
||||
<tr class="reg"><th colspan="4">Pointers</th></tr>
|
||||
<tr class="reg"><td>0</td><td>256</td><td>SP</td><td></td></tr>
|
||||
<tr class="reg"><td>1</td><td>-1</td><td>LCL</td><td></td></tr>
|
||||
<tr class="reg"><td>2</td><td>-2</td><td>ARG</td><td></td></tr>
|
||||
<tr class="reg"><td>3</td><td>-3</td><td>THIS</td><td></td></tr>
|
||||
<tr class="reg"><td>4</td><td>-4</td><td>THAT</td><td></td></tr>
|
||||
<tr class="stack"><th colspan="4">Stack</th></tr>
|
||||
<tr class="tos"><td>256</td><td>???</td><td></td><td>←SP</td></tr>
|
||||
<tr class="note"><td colspan="4"><br>
|
||||
This is how my boot­strap code initial­izes the pointers before calling Sys.init().
|
||||
<p>
|
||||
Setting the LCL, ARG, THIS and THAT point­ers to known illegal values helps identify
|
||||
when a pointer is used before it is initial­ized.
|
||||
<p>
|
||||
(If you are running the NestedCall test with­out boot­strap code, you will not see this state.)</td></tr>
|
||||
</table>
|
||||
</td><td>
|
||||
<table class="stack">
|
||||
<tr><th colspan="4">Entry to Sys.init()</th></tr>
|
||||
<tr class="reg"><th colspan="4">Pointers</th></tr>
|
||||
<tr class="reg"><td>0</td><td>261</td><td>SP</td><td></td></tr>
|
||||
<tr class="reg"><td>1</td><td>261</td><td>LCL</td><td></td></tr>
|
||||
<tr class="reg"><td>2</td><td>256</td><td>ARG</td><td></td></tr>
|
||||
<tr class="reg"><td>3</td><td>-3</td><td>THIS</td><td></td></tr>
|
||||
<tr class="reg"><td>4</td><td>-4</td><td>THAT</td><td></td></tr>
|
||||
<tr class="stack"><th colspan="4">Stack</th></tr>
|
||||
<tr class="bframet"><td>256</td><td>*</td><td>Return IP</td><td>←ARG</td></tr>
|
||||
<tr class="bframe"><td>257</td><td>-1</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="bframe"><td>258</td><td>-2</td><td>Saved ARG</td><td class="fid">Sys.init</td></tr>
|
||||
<tr class="bframe"><td>259</td><td>-3</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="bframeb"><td>260</td><td>-4</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="tos"><td>261</td><td>???</td><td></td><td>←LCL, SP</td></tr>
|
||||
<tr class="note"><td colspan="4"><br>
|
||||
This is how NestedCall.tst initial­izes the pointers and stack. This is what RAM looks
|
||||
like after my boot­strap calls Sys.init().
|
||||
<p>
|
||||
(If your VM trans­lation includes the boot­strap, the -1 through -4 values may be
|
||||
different if your boot­strap initial­izes them.)</td></tr>
|
||||
</table>
|
||||
</td><td>
|
||||
<table class="stack">
|
||||
<tr><th colspan="4">Entry to Sys.main()</th></tr>
|
||||
<tr class="reg"><th colspan="4">Pointers</th></tr>
|
||||
<tr class="reg"><td>0</td><td>266</td><td>SP</td><td></td></tr>
|
||||
<tr class="reg"><td>1</td><td>266</td><td>LCL</td><td></td></tr>
|
||||
<tr class="reg"><td>2</td><td>261</td><td>ARG</td><td></td></tr>
|
||||
<tr class="reg"><td>3</td><td>4000</td><td>THIS</td><td></td></tr>
|
||||
<tr class="reg"><td>4</td><td>5000</td><td>THAT</td><td></td></tr>
|
||||
<tr class="stack"><th colspan="4">Stack</th></tr>
|
||||
<tr class="framet"><td>256</td><td>*</td><td>Return IP</td><td></td></tr>
|
||||
<tr class="frame"><td>257</td><td>-1</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="frame"><td>258</td><td>-2</td><td>Saved ARG</td><td class="fid">Sys.init</td></tr>
|
||||
<tr class="frame"><td>259</td><td>-3</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="frame"><td>260</td><td>-4</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="bframet"><td>261</td><td>*</td><td>Return IP</td><td>←ARG</td></tr>
|
||||
<tr class="bframe"><td>262</td><td>261</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="bframe"><td>263</td><td>256</td><td>Saved ARG</td><td class="fid">Sys.main</td></tr>
|
||||
<tr class="bframe"><td>264</td><td>4000</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="bframeb"><td>265</td><td>5000</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="tos"><td>266</td><td>???</td><td></td><td>←LCL, SP</td></tr>
|
||||
</table>
|
||||
</td><td>
|
||||
<table class="stack">
|
||||
<tr><th colspan="4">After Sys.main() prologue</th></tr>
|
||||
<tr class="reg"><th colspan="4">Pointers</th></tr>
|
||||
<tr class="reg"><td>0</td><td>271</td><td>SP</td><td></td></tr>
|
||||
<tr class="reg"><td>1</td><td>266</td><td>LCL</td><td></td></tr>
|
||||
<tr class="reg"><td>2</td><td>261</td><td>ARG</td><td></td></tr>
|
||||
<tr class="reg"><td>3</td><td>4000</td><td>THIS</td><td></td></tr>
|
||||
<tr class="reg"><td>4</td><td>5000</td><td>THAT</td><td></td></tr>
|
||||
<tr class="stack"><th colspan="4">Stack</th></tr>
|
||||
<tr class="framet"><td>256</td><td>*</td><td>Return IP</td><td></td></tr>
|
||||
<tr class="frame"><td>257</td><td>-1</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="frame"><td>258</td><td>-2</td><td>Saved ARG</td><td class="fid">Sys.init</td></tr>
|
||||
<tr class="frame"><td>259</td><td>-3</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="frame"><td>260</td><td>-4</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="bframet"><td>261</td><td>*</td><td>Return IP</td><td>←ARG</td></tr>
|
||||
<tr class="bframe"><td>262</td><td>261</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="bframe"><td>263</td><td>256</td><td>Saved ARG</td><td class="fid">Sys.main</td></tr>
|
||||
<tr class="bframe"><td>264</td><td>4000</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="bframe"><td>265</td><td>5000</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="bframe"><td>266</td><td>0</td><td>local 0</td><td>←LCL</td></tr>
|
||||
<tr class="bframe"><td>267</td><td>0</td><td>local 1</td><td></td></tr>
|
||||
<tr class="bframe"><td>268</td><td>0</td><td>local 2</td><td></td></tr>
|
||||
<tr class="bframe"><td>269</td><td>0</td><td>local 3</td><td></td></tr>
|
||||
<tr class="bframeb"><td>270</td><td>0</td><td>local 4</td><td></td></tr>
|
||||
<tr class="tos"><td>271</td><td>???</td><td></td><td>←SP</td></tr>
|
||||
<tr class="note"><td colspan="4"><br>
|
||||
The <i>function prologue</i> is the assembly language code generated for the
|
||||
"function" VM command.
|
||||
</table>
|
||||
</td><td>
|
||||
<table class="stack">
|
||||
<tr><th colspan="4">Entry to Sys.add12(123)</th></tr>
|
||||
<tr class="reg"><th colspan="4">Pointers</th></tr>
|
||||
<tr class="reg"><td>0</td><td>277</td><td>SP</td><td></td></tr>
|
||||
<tr class="reg"><td>1</td><td>277</td><td>LCL</td><td></td></tr>
|
||||
<tr class="reg"><td>2</td><td>271</td><td>ARG</td><td></td></tr>
|
||||
<tr class="reg"><td>3</td><td>4001</td><td>THIS</td><td></td></tr>
|
||||
<tr class="reg"><td>4</td><td>5001</td><td>THAT</td><td></td></tr>
|
||||
<tr class="stack"><th colspan="4">Stack</th></tr>
|
||||
<tr class="framet"><td>256</td><td>*</td><td>Return IP</td><td></td></tr>
|
||||
<tr class="frame"><td>257</td><td>-1</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="frame"><td>258</td><td>-2</td><td>Saved ARG</td><td class="fid">Sys.init</td></tr>
|
||||
<tr class="frame"><td>259</td><td>-3</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="frame"><td>260</td><td>-4</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="framet"><td>261</td><td>*</td><td>Return IP</td><td></td></tr>
|
||||
<tr class="frame"><td>262</td><td>261</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="frame"><td>263</td><td>256</td><td>Saved ARG</td><td class="fid">Sys.main</td></tr>
|
||||
<tr class="frame"><td>264</td><td>4000</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="frame"><td>265</td><td>5000</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="frame"><td>266</td><td>0</td><td>local 0</td><td></td></tr>
|
||||
<tr class="frame"><td>267</td><td>200</td><td>local 1</td><td></td></tr>
|
||||
<tr class="frame"><td>268</td><td>40</td><td>local 2</td><td></td></tr>
|
||||
<tr class="frame"><td>269</td><td>6</td><td>local 3</td><td></td></tr>
|
||||
<tr class="frame"><td>270</td><td>0</td><td>local 4</td><td></td></tr>
|
||||
<tr class="bframet"><td>271</td><td>123</td><td>argument 0</td><td>←ARG</td></tr>
|
||||
<tr class="bframe"><td>272</td><td>*</td><td>Return IP</td><td></td></tr>
|
||||
<tr class="bframe"><td>273</td><td>266</td><td>Saved LCL</td><td class="fid">Sys.add12</td></tr>
|
||||
<tr class="bframe"><td>274</td><td>261</td><td>Saved ARG</td><td class="fid"> frame</td></tr>
|
||||
<tr class="bframe"><td>275</td><td>4001</td><td>Saved THIS</td><td></td></tr>
|
||||
<tr class="bframeb"><td>276</td><td>5001</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="tos"><td>277</td><td>???</td><td></td><td>←LCL, SP</td></tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr></table>
|
||||
|
||||
<p>
|
||||
|
||||
<table class="master">
|
||||
<tr>
|
||||
<td>
|
||||
<table class="stack">
|
||||
<tr><th colspan="4">Before Sys.add12() return</th></tr>
|
||||
<tr class="reg"><th colspan="4">Pointers</th></tr>
|
||||
<tr class="reg"><td>0</td><td>278</td><td>SP</td><td></td></tr>
|
||||
<tr class="reg"><td>1</td><td>277</td><td>LCL</td><td></td></tr>
|
||||
<tr class="reg"><td>2</td><td>271</td><td>ARG</td><td></td></tr>
|
||||
<tr class="reg"><td>3</td><td>4002</td><td>THIS</td><td></td></tr>
|
||||
<tr class="reg"><td>4</td><td>5002</td><td>THAT</td><td></td></tr>
|
||||
<tr class="stack"><th colspan="4">Stack</th></tr>
|
||||
<tr class="framet"><td>256</td><td>*</td><td>Return IP</td><td></td></tr>
|
||||
<tr class="frame"><td>257</td><td>-1</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="frame"><td>258</td><td>-2</td><td>Saved ARG</td><td class="fid">Sys.init</td></tr>
|
||||
<tr class="frame"><td>259</td><td>-3</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="frame"><td>260</td><td>-4</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="framet"><td>261</td><td>*</td><td>Return IP</td><td></td></tr>
|
||||
<tr class="frame"><td>262</td><td>261</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="frame"><td>263</td><td>256</td><td>Saved ARG</td><td class="fid">Sys.main</td></tr>
|
||||
<tr class="frame"><td>264</td><td>4000</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="frame"><td>265</td><td>5000</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="frame"><td>266</td><td>0</td><td>local 0</td><td></td></tr>
|
||||
<tr class="frame"><td>267</td><td>200</td><td>local 1</td><td></td></tr>
|
||||
<tr class="frame"><td>268</td><td>40</td><td>local 2</td><td></td></tr>
|
||||
<tr class="frame"><td>269</td><td>6</td><td>local 3</td><td></td></tr>
|
||||
<tr class="frame"><td>270</td><td>0</td><td>local 4</td><td></td></tr>
|
||||
<tr class="bframet"><td>271</td><td>123</td><td>argument 0</td><td>←ARG</td></tr>
|
||||
<tr class="bframe"><td>272</td><td>*</td><td>Return IP</td><td></td></tr>
|
||||
<tr class="bframe"><td>273</td><td>266</td><td>Saved LCL</td><td class="fid">Sys.add12</td></tr>
|
||||
<tr class="bframe"><td>274</td><td>261</td><td>Saved ARG</td><td class="fid"> frame</td></tr>
|
||||
<tr class="bframe"><td>275</td><td>4001</td><td>Saved THIS</td><td></td></tr>
|
||||
<tr class="bframe"><td>276</td><td>5001</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="bframeb"><td>277</td><td>135</td><td>Return value</td><td>←LCL</td></tr>
|
||||
<tr class="tos"><td>278</td><td>???</td><td></td><td>←SP</td></tr>
|
||||
</table>
|
||||
</td><td>
|
||||
<table class="stack">
|
||||
<tr><th colspan="4">After Sys.add12() return</th></tr>
|
||||
<tr class="reg"><th colspan="4">Pointers</th></tr>
|
||||
<tr class="reg"><td>0</td><td>272</td><td>SP</td><td></td></tr>
|
||||
<tr class="reg"><td>1</td><td>266</td><td>LCL</td><td></td></tr>
|
||||
<tr class="reg"><td>2</td><td>261</td><td>ARG</td><td></td></tr>
|
||||
<tr class="reg"><td>3</td><td>4001</td><td>THIS</td><td></td></tr>
|
||||
<tr class="reg"><td>4</td><td>5001</td><td>THAT</td><td></td></tr>
|
||||
<tr class="stack"><th colspan="4">Stack</th></tr>
|
||||
<tr class="framet"><td>256</td><td>*</td><td>Return IP</td><td></td></tr>
|
||||
<tr class="frame"><td>257</td><td>-1</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="frame"><td>258</td><td>-2</td><td>Saved ARG</td><td class="fid">Sys.init</td></tr>
|
||||
<tr class="frame"><td>259</td><td>-3</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="frame"><td>260</td><td>-4</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="bframet"><td>261</td><td>*</td><td>Return IP</td><td>←ARG</td></tr>
|
||||
<tr class="bframe"><td>262</td><td>261</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="bframe"><td>263</td><td>256</td><td>Saved ARG</td><td class="fid">Sys.main</td></tr>
|
||||
<tr class="bframe"><td>264</td><td>4000</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="bframe"><td>265</td><td>5000</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="bframe"><td>266</td><td>0</td><td>local 0</td><td>←LCL</td></tr>
|
||||
<tr class="bframe"><td>267</td><td>200</td><td>local 1</td><td></td></tr>
|
||||
<tr class="bframe"><td>268</td><td>40</td><td>local 2</td><td></td></tr>
|
||||
<tr class="bframe"><td>269</td><td>6</td><td>local 3</td><td></td></tr>
|
||||
<tr class="bframe"><td>270</td><td>0</td><td>local 4</td><td></td></tr>
|
||||
<tr class="bframeb"><td>271</td><td>135</td><td>Return value</td><td></td></tr>
|
||||
<tr class="tos"><td>272</td><td>???</td><td></td><td>←SP</td></tr>
|
||||
</table>
|
||||
</td><td>
|
||||
<table class="stack">
|
||||
<tr><th colspan="4">Before Sys.main() return</th></tr>
|
||||
<tr class="reg"><th colspan="4">Pointers</th></tr>
|
||||
<tr class="reg"><td>0</td><td>272</td><td>SP</td><td></td></tr>
|
||||
<tr class="reg"><td>1</td><td>266</td><td>LCL</td><td></td></tr>
|
||||
<tr class="reg"><td>2</td><td>261</td><td>ARG</td><td></td></tr>
|
||||
<tr class="reg"><td>3</td><td>4001</td><td>THIS</td><td></td></tr>
|
||||
<tr class="reg"><td>4</td><td>5001</td><td>THAT</td><td></td></tr>
|
||||
<tr class="stack"><th colspan="4">Stack</th></tr>
|
||||
<tr class="framet"><td>256</td><td>*</td><td>Return IP</td><td></td></tr>
|
||||
<tr class="frame"><td>257</td><td>-1</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="frame"><td>258</td><td>-2</td><td>Saved ARG</td><td class="fid">Sys.init</td></tr>
|
||||
<tr class="frame"><td>259</td><td>-3</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="frame"><td>260</td><td>-4</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="bframet"><td>261</td><td>*</td><td>Return IP</td><td>←ARG</td></tr>
|
||||
<tr class="bframe"><td>262</td><td>261</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="bframe"><td>263</td><td>256</td><td>Saved ARG</td><td class="fid">Sys.main</td></tr>
|
||||
<tr class="bframe"><td>264</td><td>4000</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="bframe"><td>265</td><td>5000</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="bframe"><td>266</td><td>0</td><td>local 0</td><td>←LCL</td></tr>
|
||||
<tr class="bframe"><td>267</td><td>200</td><td>local 1</td><td></td></tr>
|
||||
<tr class="bframe"><td>268</td><td>40</td><td>local 2</td><td></td></tr>
|
||||
<tr class="bframe"><td>269</td><td>6</td><td>local 3</td><td></td></tr>
|
||||
<tr class="bframe"><td>270</td><td>0</td><td>local 4</td><td></td></tr>
|
||||
<tr class="bframeb"><td>271</td><td>246</td><td>Return value</td><td></td></tr>
|
||||
<tr class="tos"><td>272</td><td>???</td><td></td><td>←SP</td></tr>
|
||||
</table>
|
||||
</td><td>
|
||||
<table class="stack">
|
||||
<tr><th colspan="4">After Sys.main() return</th></tr>
|
||||
<tr class="reg"><th colspan="4">Pointers</th></tr>
|
||||
<tr class="reg"><td>0</td><td>262</td><td>SP</td><td></td></tr>
|
||||
<tr class="reg"><td>1</td><td>261</td><td>LCL</td><td></td></tr>
|
||||
<tr class="reg"><td>2</td><td>256</td><td>ARG</td><td></td></tr>
|
||||
<tr class="reg"><td>3</td><td>4000</td><td>THIS</td><td></td></tr>
|
||||
<tr class="reg"><td>4</td><td>5000</td><td>THAT</td><td></td></tr>
|
||||
<tr class="stack"><th colspan="4">Stack</th></tr>
|
||||
<tr class="bframet"><td>256</td><td>*</td><td>Return IP</td><td>←ARG</td></tr>
|
||||
<tr class="bframe"><td>257</td><td>-1</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="bframe"><td>258</td><td>-2</td><td>Saved ARG</td><td class="fid">Sys.init</td></tr>
|
||||
<tr class="bframe"><td>259</td><td>-3</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="bframe"><td>260</td><td>-4</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="bframeb"><td>261</td><td>246</td><td>Return value</td><td>←LCL</td></tr>
|
||||
<tr class="tos"><td>262</td><td>???</td><td></td><td>←SP</td></tr>
|
||||
</table>
|
||||
</td><td>
|
||||
<table class="stack">
|
||||
<tr><th colspan="4">In Sys.init() halt loop</th></tr>
|
||||
<tr class="reg"><th colspan="4">Pointers</th></tr>
|
||||
<tr class="reg"><td>0</td><td>261</td><td>SP</td><td></td></tr>
|
||||
<tr class="reg"><td>1</td><td>261</td><td>LCL</td><td></td></tr>
|
||||
<tr class="reg"><td>2</td><td>256</td><td>ARG</td><td></td></tr>
|
||||
<tr class="reg"><td>3</td><td>4000</td><td>THIS</td><td></td></tr>
|
||||
<tr class="reg"><td>4</td><td>5000</td><td>THAT</td><td></td></tr>
|
||||
<tr class="stack"><th colspan="4">Stack</th></tr>
|
||||
<tr class="bframet"><td>256</td><td>*</td><td>Return IP</td><td>←ARG</td></tr>
|
||||
<tr class="bframe"><td>257</td><td>-1</td><td>Saved LCL</td><td></td></tr>
|
||||
<tr class="bframe"><td>258</td><td>-2</td><td>Saved ARG</td><td class="fid">Sys.init</td></tr>
|
||||
<tr class="bframe"><td>259</td><td>-3</td><td>Saved THIS</td><td class="fid"> frame</td></tr>
|
||||
<tr class="bframeb"><td>260</td><td>-4</td><td>Saved THAT</td><td></td></tr>
|
||||
<tr class="tos"><td>261</td><td>???</td><td></td><td>←LCL, SP</td></tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr></table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
72
08/FunctionCalls/NestedCall/NestedCallVME.tst
Normal file
72
08/FunctionCalls/NestedCall/NestedCallVME.tst
Normal file
@@ -0,0 +1,72 @@
|
||||
// Tests and illustrates how the VM implementation handles function-call-and-return,
|
||||
// by executing the functions in Sys.vm in the VM emulator.
|
||||
// In particular, loads and runs the functions in Sys.vm.
|
||||
|
||||
load Sys.vm,
|
||||
output-file NestedCall.out,
|
||||
compare-to NestedCall.cmp,
|
||||
output-list RAM[0]%D1.6.1 RAM[1]%D1.6.1 RAM[2]%D1.6.1 RAM[3]%D1.6.1 RAM[4]%D1.6.1 RAM[5]%D1.6.1 RAM[6]%D1.6.1;
|
||||
|
||||
set RAM[0] 261,
|
||||
set RAM[1] 261,
|
||||
set RAM[2] 256,
|
||||
set RAM[3] -3,
|
||||
set RAM[4] -4,
|
||||
set RAM[5] -1, // test results
|
||||
set RAM[6] -1,
|
||||
set RAM[256] 1234, // fake stack frame from call Sys.init
|
||||
set RAM[257] -1,
|
||||
set RAM[258] -2,
|
||||
set RAM[259] -3,
|
||||
set RAM[260] -4,
|
||||
|
||||
set RAM[261] -1, // Initialize stack to check for local segment
|
||||
set RAM[262] -1, // being cleared to zero.
|
||||
set RAM[263] -1,
|
||||
set RAM[264] -1,
|
||||
set RAM[265] -1,
|
||||
set RAM[266] -1,
|
||||
set RAM[267] -1,
|
||||
set RAM[268] -1,
|
||||
set RAM[269] -1,
|
||||
set RAM[270] -1,
|
||||
set RAM[271] -1,
|
||||
set RAM[272] -1,
|
||||
set RAM[273] -1,
|
||||
set RAM[274] -1,
|
||||
set RAM[275] -1,
|
||||
set RAM[276] -1,
|
||||
set RAM[277] -1,
|
||||
set RAM[278] -1,
|
||||
set RAM[279] -1,
|
||||
set RAM[280] -1,
|
||||
set RAM[281] -1,
|
||||
set RAM[282] -1,
|
||||
set RAM[283] -1,
|
||||
set RAM[284] -1,
|
||||
set RAM[285] -1,
|
||||
set RAM[286] -1,
|
||||
set RAM[287] -1,
|
||||
set RAM[288] -1,
|
||||
set RAM[289] -1,
|
||||
set RAM[290] -1,
|
||||
set RAM[291] -1,
|
||||
set RAM[292] -1,
|
||||
set RAM[293] -1,
|
||||
set RAM[294] -1,
|
||||
set RAM[295] -1,
|
||||
set RAM[296] -1,
|
||||
set RAM[297] -1,
|
||||
set RAM[298] -1,
|
||||
set RAM[299] -1,
|
||||
|
||||
set sp 261,
|
||||
set local 261,
|
||||
set argument 256,
|
||||
set this 3000,
|
||||
set that 4000;
|
||||
|
||||
repeat 50 {
|
||||
vmstep;
|
||||
}
|
||||
output;
|
||||
57
08/FunctionCalls/NestedCall/Sys.vm
Normal file
57
08/FunctionCalls/NestedCall/Sys.vm
Normal file
@@ -0,0 +1,57 @@
|
||||
// Sys.vm. Tested by the NestedCall test script.
|
||||
// Consists of three functions: Sys.init, Sys.main, and Sys.add12.
|
||||
|
||||
// Calls Sys.main() and stores a return value in temp 1.
|
||||
// Does not return (enters infinite loop).
|
||||
// The VM implementation starts running the Sys.init function, by default.
|
||||
function Sys.init 0
|
||||
push constant 4000 // tests that THIS and THAT are handled correctly
|
||||
pop pointer 0
|
||||
push constant 5000
|
||||
pop pointer 1
|
||||
call Sys.main 0
|
||||
pop temp 1
|
||||
label LOOP
|
||||
goto LOOP
|
||||
|
||||
// Sets locals 1, 2 and 3 to some values. Leaves locals 0 and 4 unchanged,
|
||||
// to test that the 'function' VM command initliazes them to 0 (the test
|
||||
// script sets them to -1 before this code starts running).
|
||||
// Calls Sys.add12(123) and stores the return value (should be 135) in temp 0.
|
||||
// Returns local 0 + local 1 + local 2 + local 3 + local 4 (should be 456), to
|
||||
// confirm that locals were not mangled by the function call.
|
||||
function Sys.main 5
|
||||
push constant 4001
|
||||
pop pointer 0
|
||||
push constant 5001
|
||||
pop pointer 1
|
||||
push constant 200
|
||||
pop local 1
|
||||
push constant 40
|
||||
pop local 2
|
||||
push constant 6
|
||||
pop local 3
|
||||
push constant 123
|
||||
call Sys.add12 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
push local 1
|
||||
push local 2
|
||||
push local 3
|
||||
push local 4
|
||||
add
|
||||
add
|
||||
add
|
||||
add
|
||||
return
|
||||
|
||||
// Returns (argument 0) + 12.
|
||||
function Sys.add12 0
|
||||
push constant 4002
|
||||
pop pointer 0
|
||||
push constant 5002
|
||||
pop pointer 1
|
||||
push argument 0
|
||||
push constant 12
|
||||
add
|
||||
return
|
||||
37
08/FunctionCalls/SimpleFunction/SimpleFunction.tst
Normal file
37
08/FunctionCalls/SimpleFunction/SimpleFunction.tst
Normal file
@@ -0,0 +1,37 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/FunctionCalls/SimpleFunction/SimpleFunction.tst
|
||||
|
||||
// Tests SimpleFunction.asm in the CPU emulator.
|
||||
// In particular, tests how the assembly implementation of the 'function'
|
||||
// VM command initializes local variables, and how the assembly implementation
|
||||
// of the 'return' VM command handles the return value, SP, LCL, ARG, THIS, and THAT.
|
||||
// Before executing the code, initializes the stack pointer and the pointers of some
|
||||
// of the memory segments, and sets some values in the argument segment.
|
||||
|
||||
load SimpleFunction.asm,
|
||||
output-file SimpleFunction.out,
|
||||
compare-to SimpleFunction.cmp,
|
||||
|
||||
set RAM[0] 317, // SP
|
||||
set RAM[1] 317, // LCL
|
||||
set RAM[2] 310, // ARG
|
||||
set RAM[3] 3000, // THIS
|
||||
set RAM[4] 4000, // THAT
|
||||
set RAM[310] 1234,
|
||||
set RAM[311] 37,
|
||||
set RAM[312] 1000,
|
||||
set RAM[313] 305,
|
||||
set RAM[314] 300,
|
||||
set RAM[315] 3010,
|
||||
set RAM[316] 4010,
|
||||
|
||||
repeat 300 {
|
||||
ticktock;
|
||||
}
|
||||
|
||||
// Outputs SP, LCL, ARG, THIS, THAT, and the return value.
|
||||
output-list RAM[0]%D1.6.1 RAM[1]%D1.6.1 RAM[2]%D1.6.1
|
||||
RAM[3]%D1.6.1 RAM[4]%D1.6.1 RAM[310]%D1.6.1;
|
||||
output;
|
||||
18
08/FunctionCalls/SimpleFunction/SimpleFunction.vm
Normal file
18
08/FunctionCalls/SimpleFunction/SimpleFunction.vm
Normal file
@@ -0,0 +1,18 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/FunctionCalls/SimpleFunction/SimpleFunction.vm
|
||||
|
||||
// Performs a simple calculation and returns the result.
|
||||
// argument[0] and argument[1] must be set by the caller.
|
||||
|
||||
function SimpleFunction.test 2
|
||||
push local 0
|
||||
push local 1
|
||||
add
|
||||
not
|
||||
push argument 0
|
||||
add
|
||||
push argument 1
|
||||
sub
|
||||
return
|
||||
35
08/FunctionCalls/SimpleFunction/SimpleFunctionVME.tst
Normal file
35
08/FunctionCalls/SimpleFunction/SimpleFunctionVME.tst
Normal file
@@ -0,0 +1,35 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/FunctionCalls/SimpleFunction/SimpleFunctionVME.tst
|
||||
|
||||
// Tests and illustrates SimpleFunction.vm in the VM emulator.
|
||||
// Before executing the code, initializes the stack pointer
|
||||
// and the base addresses of some of the memory segments,
|
||||
// and sets some values in the argument segment.
|
||||
|
||||
load SimpleFunction.vm,
|
||||
output-file SimpleFunction.out,
|
||||
compare-to SimpleFunction.cmp,
|
||||
|
||||
set sp 317,
|
||||
set local 317,
|
||||
set argument 310,
|
||||
set this 3000,
|
||||
set that 4000,
|
||||
set argument[0] 1234,
|
||||
set argument[1] 37,
|
||||
set argument[2] 9,
|
||||
set argument[3] 305,
|
||||
set argument[4] 300,
|
||||
set argument[5] 3010,
|
||||
set argument[6] 4010,
|
||||
|
||||
repeat 10 {
|
||||
vmstep;
|
||||
}
|
||||
|
||||
// Outputs SP, LCL, ARG, THIS, THAT, and the return value.
|
||||
output-list RAM[0]%D1.6.1 RAM[1]%D1.6.1 RAM[2]%D1.6.1
|
||||
RAM[3]%D1.6.1 RAM[4]%D1.6.1 RAM[310]%D1.6.1;
|
||||
output;
|
||||
20
08/FunctionCalls/StaticsTest/Class1.vm
Normal file
20
08/FunctionCalls/StaticsTest/Class1.vm
Normal file
@@ -0,0 +1,20 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/FunctionCalls/StaticsTest/Class1.vm
|
||||
|
||||
// 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
|
||||
20
08/FunctionCalls/StaticsTest/Class2.vm
Normal file
20
08/FunctionCalls/StaticsTest/Class2.vm
Normal file
@@ -0,0 +1,20 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/FunctionCalls/StaticsTest/Class2.vm
|
||||
|
||||
// Stores two supplied arguments in static[0] and static[1].
|
||||
function Class2.set 0
|
||||
push argument 0
|
||||
pop static 0
|
||||
push argument 1
|
||||
pop static 1
|
||||
push constant 0
|
||||
return
|
||||
|
||||
// Returns static[0] - static[1].
|
||||
function Class2.get 0
|
||||
push static 0
|
||||
push static 1
|
||||
sub
|
||||
return
|
||||
20
08/FunctionCalls/StaticsTest/StaticsTest.tst
Normal file
20
08/FunctionCalls/StaticsTest/StaticsTest.tst
Normal file
@@ -0,0 +1,20 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/FunctionCalls/StaticsTest/StaticsTest.tst
|
||||
|
||||
// Tests StaticTest.asm in the CPU emulator.
|
||||
// This assembly file results from translating the staticsTest folder.
|
||||
|
||||
load StaticsTest.asm,
|
||||
output-file StaticsTest.out,
|
||||
compare-to StaticsTest.cmp,
|
||||
|
||||
set RAM[0] 256,
|
||||
|
||||
repeat 2500 {
|
||||
ticktock;
|
||||
}
|
||||
|
||||
output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1 RAM[262]%D1.6.1;
|
||||
output;
|
||||
19
08/FunctionCalls/StaticsTest/StaticsTestVME.tst
Normal file
19
08/FunctionCalls/StaticsTest/StaticsTestVME.tst
Normal file
@@ -0,0 +1,19 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/FunctionCalls/StaticsTest/StaticsTestVME.tst
|
||||
|
||||
// Tests and illustrates the statics test on the VM emulator.
|
||||
|
||||
load, // loads all the VM files from the current folder
|
||||
output-file StaticsTest.out,
|
||||
compare-to StaticsTest.cmp,
|
||||
|
||||
set sp 261,
|
||||
|
||||
repeat 36 {
|
||||
vmstep;
|
||||
}
|
||||
|
||||
output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1 RAM[262]%D1.6.1;
|
||||
output;
|
||||
21
08/FunctionCalls/StaticsTest/Sys.vm
Normal file
21
08/FunctionCalls/StaticsTest/Sys.vm
Normal file
@@ -0,0 +1,21 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/FunctionCalls/StaticsTest/Sys.vm
|
||||
|
||||
// Tests that different functions, stored in two different
|
||||
// class files, manipulate the static segment correctly.
|
||||
|
||||
function Sys.init 0
|
||||
push constant 6
|
||||
push constant 8
|
||||
call Class1.set 2
|
||||
pop temp 0 // dumps the return value
|
||||
push constant 23
|
||||
push constant 15
|
||||
call Class2.set 2
|
||||
pop temp 0 // dumps the return value
|
||||
call Class1.get 0
|
||||
call Class2.get 0
|
||||
label END
|
||||
goto END
|
||||
26
08/ProgramFlow/BasicLoop/BasicLoop.tst
Normal file
26
08/ProgramFlow/BasicLoop/BasicLoop.tst
Normal file
@@ -0,0 +1,26 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/ProgramFlow/BasicLoop/BasicLoop.tst
|
||||
|
||||
// Tests BasicLoop.asm on the CPU emulator.
|
||||
// Before executing the code, initializes the stack pointer
|
||||
// and the base addresses of the local and argument segments,
|
||||
// and sets argument[0].
|
||||
|
||||
load BasicLoop.asm,
|
||||
output-file BasicLoop.out,
|
||||
compare-to BasicLoop.cmp,
|
||||
|
||||
set RAM[0] 256, // SP
|
||||
set RAM[1] 300, // LCL
|
||||
set RAM[2] 400, // ARG
|
||||
set RAM[400] 3, // argument 0
|
||||
|
||||
repeat 600 {
|
||||
ticktock;
|
||||
}
|
||||
|
||||
// Outputs the stack pointer and the value at the stack's base
|
||||
output-list RAM[0]%D1.6.1 RAM[256]%D1.6.1;
|
||||
output;
|
||||
23
08/ProgramFlow/BasicLoop/BasicLoop.vm
Normal file
23
08/ProgramFlow/BasicLoop/BasicLoop.vm
Normal file
@@ -0,0 +1,23 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/ProgramFlow/BasicLoop/BasicLoop.vm
|
||||
|
||||
// Computes the sum 1 + 2 + ... + n and pushes the result onto
|
||||
// the stack. The value n is given in argument[0], which must be
|
||||
// initialized by the caller of this code.
|
||||
|
||||
push constant 0
|
||||
pop local 0 // sum = 0
|
||||
label LOOP
|
||||
push argument 0
|
||||
push local 0
|
||||
add
|
||||
pop local 0 // sum = sum + n
|
||||
push argument 0
|
||||
push constant 1
|
||||
sub
|
||||
pop argument 0 // n--
|
||||
push argument 0
|
||||
if-goto LOOP // if n > 0, goto LOOP
|
||||
push local 0 // else, pushes sum to the stack's top
|
||||
26
08/ProgramFlow/BasicLoop/BasicLoopVME.tst
Normal file
26
08/ProgramFlow/BasicLoop/BasicLoopVME.tst
Normal file
@@ -0,0 +1,26 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/ProgramFlow/BasicLoop/BasicLoopVME.tst
|
||||
|
||||
// Tests and illustrates BasicLoop.vm on the VM emulator.
|
||||
// Before executing the code, initializes the stack pointer
|
||||
// and the base addresses of the local and argument segments,
|
||||
// and sets argument[0].
|
||||
|
||||
load BasicLoop.vm,
|
||||
output-file BasicLoop.out,
|
||||
compare-to BasicLoop.cmp,
|
||||
|
||||
set sp 256,
|
||||
set local 300,
|
||||
set argument 400,
|
||||
set argument[0] 3,
|
||||
|
||||
repeat 33 {
|
||||
vmstep;
|
||||
}
|
||||
|
||||
// Outputs the stack pointer and the value at the stack's base
|
||||
output-list RAM[0]%D1.6.1 RAM[256]%D1.6.1;
|
||||
output;
|
||||
28
08/ProgramFlow/FibonacciSeries/FibonacciSeries.tst
Normal file
28
08/ProgramFlow/FibonacciSeries/FibonacciSeries.tst
Normal file
@@ -0,0 +1,28 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/ProgramFlow/FibonacciSeries/FibonacciSeries.tst
|
||||
|
||||
// Tests FibonacciSeries.asm on the CPU emulator.
|
||||
// Before executing the code, initializes the stack pointer
|
||||
// and the base addresses of the local and argument segments,
|
||||
// and sets argument[0] and argument [1].
|
||||
|
||||
load FibonacciSeries.asm,
|
||||
output-file FibonacciSeries.out,
|
||||
compare-to FibonacciSeries.cmp,
|
||||
|
||||
set RAM[0] 256, // SP
|
||||
set RAM[1] 300, // LCL
|
||||
set RAM[2] 400, // ARG
|
||||
set RAM[400] 6, // argument[0], n
|
||||
set RAM[401] 3000, // argument[1], base address of the generated series
|
||||
|
||||
repeat 1100 {
|
||||
ticktock;
|
||||
}
|
||||
|
||||
// Outputs the series of values generated and written by the code.
|
||||
output-list RAM[3000]%D1.6.2 RAM[3001]%D1.6.2 RAM[3002]%D1.6.2
|
||||
RAM[3003]%D1.6.2 RAM[3004]%D1.6.2 RAM[3005]%D1.6.2;
|
||||
output;
|
||||
44
08/ProgramFlow/FibonacciSeries/FibonacciSeries.vm
Normal file
44
08/ProgramFlow/FibonacciSeries/FibonacciSeries.vm
Normal file
@@ -0,0 +1,44 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/ProgramFlow/FibonacciSeries/FibonacciSeries.vm
|
||||
|
||||
// Puts the first n elements of the Fibonacci series in the memory,
|
||||
// starting at address addr. n and addr are given in argument[0] and
|
||||
// argument[1], which must be initialized by the caller of this code.
|
||||
|
||||
push argument 1 // sets THAT, the base address of the
|
||||
pop pointer 1 // that segment, to argument[1]
|
||||
push constant 0 // sets the series' first and second
|
||||
pop that 0 // elements to 0 and 1, respectively
|
||||
push constant 1
|
||||
pop that 1
|
||||
push argument 0 // sets n, the number of remaining elements
|
||||
push constant 2 // to be computed, to argument[0] minus 2,
|
||||
sub // since 2 elements were already computed.
|
||||
pop argument 0
|
||||
|
||||
label LOOP
|
||||
push argument 0
|
||||
if-goto COMPUTE_ELEMENT // if n > 0, goto COMPUTE_ELEMENT
|
||||
goto END // otherwise, goto END
|
||||
|
||||
label COMPUTE_ELEMENT
|
||||
// that[2] = that[0] + that[1]
|
||||
push that 0
|
||||
push that 1
|
||||
add
|
||||
pop that 2
|
||||
// THAT += 1 (updates the base address of that)
|
||||
push pointer 1
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
// updates n-- and loops
|
||||
push argument 0
|
||||
push constant 1
|
||||
sub
|
||||
pop argument 0
|
||||
goto LOOP
|
||||
|
||||
label END
|
||||
29
08/ProgramFlow/FibonacciSeries/FibonacciSeriesVME.tst
Normal file
29
08/ProgramFlow/FibonacciSeries/FibonacciSeriesVME.tst
Normal file
@@ -0,0 +1,29 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/8/ProgramFlow/FibonacciSeries/FibonacciSeriesVME.tst
|
||||
|
||||
// Tests and illustrates FibonacciSeries.vm on the VM emulator.
|
||||
// Before executing the code, initializes the stack pointer
|
||||
// and the base addresses of the local and argument segments,
|
||||
// and sets argument[0] to n and argument [1] to the base address
|
||||
// of the generated series.
|
||||
|
||||
load FibonacciSeries.vm,
|
||||
output-file FibonacciSeries.out,
|
||||
compare-to FibonacciSeries.cmp,
|
||||
|
||||
set sp 256,
|
||||
set local 300,
|
||||
set argument 400,
|
||||
set argument[0] 6,
|
||||
set argument[1] 3000,
|
||||
|
||||
repeat 73 {
|
||||
vmstep;
|
||||
}
|
||||
|
||||
// Outputs the series of values generated and written by the code.
|
||||
output-list RAM[3000]%D1.6.2 RAM[3001]%D1.6.2 RAM[3002]%D1.6.2
|
||||
RAM[3003]%D1.6.2 RAM[3004]%D1.6.2 RAM[3005]%D1.6.2;
|
||||
output;
|
||||
25
08/readme.txt
Normal file
25
08/readme.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
Project 8: Stack Flow Control (VM II)
|
||||
|
||||
The description for this project is found at:
|
||||
|
||||
https://www.nand2tetris.org/project08
|
||||
|
||||
You may _absolutely_ work as pairs on this project.
|
||||
|
||||
Hints:
|
||||
|
||||
a) Use the proposed API in chapter 8 that splits the tasks across "modules."
|
||||
|
||||
b) You will need to build upon and re-use your VMTranslator from project 7. If you didn't get it done, well, you'll need to for this project!
|
||||
|
||||
b) Test using the proposed order in chapter 8. The programs test increasingly more functionality as they go.
|
||||
|
||||
Perspective:
|
||||
|
||||
What you're building is essentially how _all_ function calls work in modern computing. Computers have an ABI (application binary interface) and these tend to be related to the C calling convention. What that means is that for a particular system (OS and platform/architecture), all programming languages use a mutually-agreed upon interface (the ABI), which when used means that a function written in and compiled frmo language A can call a function written in compiled from language B and all is well. This also means we can use standard libraries once we know the interface.
|
||||
|
||||
Most compilers (or even architectures) have their prescribed format that describes what information and the oder that it is placed on the stack. The x86 standard is similar to the VM translator you are currently writing. The way in which an OS kernel handles tasks is also similar, except that it allows multiple processes to run and switches between these. To do this, it provides each process or thread its own stack. Guess what? To switch processes, you just store everything on the current stack, set the stack pointer to the other processes' stack, pop it off, and keep going. The OS kernel is responsible for switching between the various tasks/threads and giving each process its time on the system.
|
||||
|
||||
For further reading, search for terms like "calling convention" or "ABI" which stands for Application Binary Interface. There are a few different ones out there, like ABI for x86_64 on linux, or the Micorosoft ABI, and they are how stack frames are saved on the stack and functions are called. Once you know the ABI, you can then call functions compiled in other languages. There's a lot of power this opens up.
|
||||
|
||||
Remember that the gradescope tester is including a "-y" and a "-n" flag at the end of the command. This indicates whether or not your compiler should include the bootstrap code (-y) or not (-n).
|
||||
Reference in New Issue
Block a user