This commit is contained in:
QkoSad
2025-07-16 13:00:37 +03:00
commit 7894b48931
806 changed files with 162532 additions and 0 deletions
@@ -0,0 +1,447 @@
@256
D=A
@SP
M=D
@MainLoopXYZRA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@0
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Sys.init
0;JMP
(MainLoopXYZRARA)
//CALLFUNC
(Sys.init)
@4
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@Main.fibonacci2RA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@1
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Main.fibonacci
0;JMP
(Main.fibonacci2RA)
//CALLFUNC
(Sys.init$WHILE)
//LABEL
@Sys.init$WHILE
0;JMP
//GOTO
(Main.fibonacci)
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@2
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
A=A-1
D=M-D
@TRUE0
D;JLT
@SP
A=M
A=A-1
M=0
@FALSE0
0;JMP
(TRUE0)
@SP
A=M
A=A-1
M=-1
(FALSE0)
//LT
@SP
M=M-1
A=M
D=M
@Main.fibonacci$IF_TRUE
D;JNE
//IFGOTO
@Main.fibonacci$IF_FALSE
0;JMP
//GOTO
(Main.fibonacci$IF_TRUE)
//LABEL
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@LCL
D=M
@R13
M=D
@5
D=A
@R13
D=M-D
A=D
D=M
@R14
M=D
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D
@R13
M=M-1
A=M
D=M
@THAT
M=D
@R13
M=M-1
A=M
D=M
@THIS
M=D
@R13
M=M-1
A=M
D=M
@ARG
M=D
@R13
M=M-1
A=M
D=M
@LCL
M=D
@R14
A=M
0;JMP
//RETURN
(Main.fibonacci$IF_FALSE)
//LABEL
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@2
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
A=A-1
M=M-D
//SUB
@Main.fibonacci0RA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@1
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Main.fibonacci
0;JMP
(Main.fibonacci0RA)
//CALLFUNC
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@1
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
A=A-1
M=M-D
//SUB
@Main.fibonacci1RA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@1
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Main.fibonacci
0;JMP
(Main.fibonacci1RA)
//CALLFUNC
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@LCL
D=M
@R13
M=D
@5
D=A
@R13
D=M-D
A=D
D=M
@R14
M=D
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D
@R13
M=M-1
A=M
D=M
@THAT
M=D
@R13
M=M-1
A=M
D=M
@THIS
M=D
@R13
M=M-1
A=M
D=M
@ARG
M=D
@R13
M=M-1
A=M
D=M
@LCL
M=D
@R14
A=M
0;JMP
//RETURN
@@ -0,0 +1,2 @@
| RAM[0] |RAM[261]|
| 262 | 3 |
@@ -0,0 +1,2 @@
| RAM[0] |RAM[261]|
| 262 | 3 |
@@ -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/08/FunctionCalls/FibonacciElement/FibonacciElement.tst
// FibonacciElement.asm results from translating both 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,
output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1;
repeat 6000 {
ticktock;
}
output;
@@ -0,0 +1,17 @@
// 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/08/FunctionCalls/FibonacciElement/FibonacciElementVME.tst
load, // Load all the VM files from the current directory
output-file FibonacciElement.out,
compare-to FibonacciElement.cmp,
output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1;
set sp 261,
repeat 110 {
vmstep;
}
output;
+30
View File
@@ -0,0 +1,30 @@
// 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/08/FunctionCalls/FibonacciElement/Main.vm
// 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 also pushes the argument[0]
// parameter before this code starts running.
function Main.fibonacci 0
push argument 0
push constant 2
lt // checks if n<2
if-goto IF_TRUE
goto IF_FALSE
label IF_TRUE // if n<2, return n
push argument 0
return
label IF_FALSE // if n>=2, returns fib(n-2)+fib(n-1)
push argument 0
push constant 2
sub
call Main.fibonacci 1 // computes fib(n-2)
push argument 0
push constant 1
sub
call Main.fibonacci 1 // computes fib(n-1)
add // returns fib(n-1) + fib(n-2)
return
+15
View File
@@ -0,0 +1,15 @@
// 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/08/FunctionCalls/FibonacciElement/Sys.vm
// Pushes a constant, say 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.
function Sys.init 0
push constant 4
call Main.fibonacci 1 // computes the 4'th fibonacci element
label WHILE
goto WHILE // loops infinitely
+598
View File
@@ -0,0 +1,598 @@
@256
D=A
@SP
M=D
@MainLoopXYZRA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@0
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Sys.init
0;JMP
(MainLoopXYZRARA)
//CALLFUNC
(Sys.init)
@4000
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
@3
M=D
//pop POINTER
@5000
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
@4
M=D
//pop POINTER
@Sys.main3RA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@0
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Sys.main
0;JMP
(Sys.main3RA)
//CALLFUNC
@SP
M=M-1
A=M
D=M
@6
M=D
//pop TMP
(Sys.init$LOOP)
//LABEL
@Sys.init$LOOP
0;JMP
//GOTO
(Sys.main)
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//DEFINEFUNC
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//DEFINEFUNC
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//DEFINEFUNC
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//DEFINEFUNC
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//DEFINEFUNC
@4001
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
@3
M=D
//pop POINTER
@5001
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
@4
M=D
//pop POINTER
@200
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@1
D=A
@LCL
M=M+D
@SP
M=M-1
A=M
D=M
@LCL
A=M
M=D
@1
D=A
@LCL
M=M-D
//pop LOCAL
@40
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@2
D=A
@LCL
M=M+D
@SP
M=M-1
A=M
D=M
@LCL
A=M
M=D
@2
D=A
@LCL
M=M-D
//pop LOCAL
@6
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@3
D=A
@LCL
M=M+D
@SP
M=M-1
A=M
D=M
@LCL
A=M
M=D
@3
D=A
@LCL
M=M-D
//pop LOCAL
@123
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@Sys.add124RA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@1
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Sys.add12
0;JMP
(Sys.add124RA)
//CALLFUNC
@SP
M=M-1
A=M
D=M
@5
M=D
//pop TMP
@0
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@1
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@2
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@3
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@4
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@LCL
D=M
@R13
M=D
@5
D=A
@R13
D=M-D
A=D
D=M
@R14
M=D
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D
@R13
M=M-1
A=M
D=M
@THAT
M=D
@R13
M=M-1
A=M
D=M
@THIS
M=D
@R13
M=M-1
A=M
D=M
@ARG
M=D
@R13
M=M-1
A=M
D=M
@LCL
M=D
@R14
A=M
0;JMP
//RETURN
(Sys.add12)
@4002
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
@3
M=D
//pop POINTER
@5002
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
@4
M=D
//pop POINTER
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@12
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@LCL
D=M
@R13
M=D
@5
D=A
@R13
D=M-D
A=D
D=M
@R14
M=D
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D
@R13
M=M-1
A=M
D=M
@THAT
M=D
@R13
M=M-1
A=M
D=M
@THIS
M=D
@R13
M=M-1
A=M
D=M
@ARG
M=D
@R13
M=M-1
A=M
D=M
@LCL
M=D
@R14
A=M
0;JMP
//RETURN
+2
View File
@@ -0,0 +1,2 @@
| RAM[0] | RAM[1] | RAM[2] | RAM[3] | RAM[4] | RAM[5] | RAM[6] |
| 261 | 261 | 256 | 4000 | 5000 | 135 | 246 |
+196
View File
@@ -0,0 +1,196 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>NestedCall.tst &mdash; 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 NestedCall.asm, sets up the stack to simulate the bootstrap's call to Sys.init(), then
begins execution at the beginning of NestedCall.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 NestedCall.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().
<p>
The test setup also initializes the LCL, ARG, THIS and THAT pointers to -1, -2, -3 and -4.
<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.main() 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>
&emsp;&bull;&ensp;load the NestedCall.tst file,<br>
&emsp;&bull;&ensp;set a PC breakpoint at the ROM address for <span class="code">(Sys.main)</span>,<br>
&emsp;&bull;&ensp;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>
+2
View File
@@ -0,0 +1,2 @@
| RAM[0] | RAM[1] | RAM[2] | RAM[3] | RAM[4] | RAM[5] | RAM[6] |
| 261 | 261 | 256 | 4000 | 5000 | 135 | 246 |
+65
View File
@@ -0,0 +1,65 @@
// Test file for NestedCall test.
load NestedCall.asm,
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,
repeat 4000 {
ticktock;
}
output;
+306
View File
@@ -0,0 +1,306 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>NestedCall.tst &mdash; 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>&larr;SP</td></tr>
<tr class="note"><td colspan="4"><br>
This is how my boot&shy;strap code initial&shy;izes the pointers before calling Sys.init().
<p>
Setting the LCL, ARG, THIS and THAT point&shy;ers to known illegal values helps identify
when a pointer is used before it is initial&shy;ized.
<p>
(If you are running the NestedCall test with&shy;out boot&shy;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>&larr;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">&ensp;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>&larr;LCL, SP</td></tr>
<tr class="note"><td colspan="4"><br>
This is how NestedCall.tst initial&shy;izes the pointers and stack. This is what RAM looks
like after my boot&shy;strap calls Sys.init().
<p>
(If your VM trans&shy;lation includes the boot&shy;strap, the -1 through -4 values may be
different if your boot&shy;strap initial&shy;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">&ensp;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>&larr;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">&ensp;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>&larr;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">&ensp;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>&larr;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">&ensp;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>&larr;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>&larr;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">&ensp;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">&ensp;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>&larr;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">&ensp;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>&larr;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">&ensp;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">&ensp;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>&larr;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">&ensp;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>&larr;LCL</td></tr>
<tr class="tos"><td>278</td><td>???</td><td></td><td>&larr;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">&ensp;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>&larr;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">&ensp;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>&larr;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>&larr;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">&ensp;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>&larr;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">&ensp;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>&larr;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>&larr;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>&larr;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">&ensp;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>&larr;LCL</td></tr>
<tr class="tos"><td>262</td><td>???</td><td></td><td>&larr;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>&larr;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">&ensp;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>&larr;LCL, SP</td></tr>
</table>
</td>
</tr></table>
</body>
</html>
+70
View File
@@ -0,0 +1,70 @@
// Test file for NestedCall test.
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;
+543
View File
@@ -0,0 +1,543 @@
(Sys.init)
@4000
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
@3
M=D
//pop POINTER
@5000
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
@4
M=D
//pop POINTER
@Sys.main3RA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@0
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Sys.main
0;JMP
(Sys.main3RA)
//CALLFUNC
@SP
M=M-1
A=M
D=M
@6
M=D
//pop TMP
(Sys.init$LOOP)
//LABEL
@Sys.init$LOOP
0;JMP
//GOTO
(Sys.main)
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//DEFINEFUNC
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//DEFINEFUNC
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//DEFINEFUNC
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//DEFINEFUNC
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//DEFINEFUNC
@4001
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
@3
M=D
//pop POINTER
@5001
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
@4
M=D
//pop POINTER
@200
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@1
D=A
@LCL
M=M+D
@SP
M=M-1
A=M
D=M
@LCL
A=M
M=D
@1
D=A
@LCL
M=M-D
//pop LOCAL
@40
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@2
D=A
@LCL
M=M+D
@SP
M=M-1
A=M
D=M
@LCL
A=M
M=D
@2
D=A
@LCL
M=M-D
//pop LOCAL
@6
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@3
D=A
@LCL
M=M+D
@SP
M=M-1
A=M
D=M
@LCL
A=M
M=D
@3
D=A
@LCL
M=M-D
//pop LOCAL
@123
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@Sys.add124RA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@1
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Sys.add12
0;JMP
(Sys.add124RA)
//CALLFUNC
@SP
M=M-1
A=M
D=M
@5
M=D
//pop TMP
@0
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@1
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@2
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@3
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@4
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@LCL
D=M
@R13
M=D
@5
D=A
@R13
D=M-D
A=D
D=M
@R14
M=D
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D
@R13
M=M-1
A=M
D=M
@THAT
M=D
@R13
M=M-1
A=M
D=M
@THIS
M=D
@R13
M=M-1
A=M
D=M
@ARG
M=D
@R13
M=M-1
A=M
D=M
@LCL
M=D
@R14
A=M
0;JMP
//RETURN
(Sys.add12)
@4002
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
@3
M=D
//pop POINTER
@5002
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
@4
M=D
//pop POINTER
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@12
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@LCL
D=M
@R13
M=D
@5
D=A
@R13
D=M-D
A=D
D=M
@R14
M=D
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D
@R13
M=M-1
A=M
D=M
@THAT
M=D
@R13
M=M-1
A=M
D=M
@THIS
M=D
@R13
M=M-1
A=M
D=M
@ARG
M=D
@R13
M=M-1
A=M
D=M
@LCL
M=D
@R14
A=M
0;JMP
//RETURN
+63
View File
@@ -0,0 +1,63 @@
// Sys.vm for NestedCall test.
// Sys.init()
//
// Calls Sys.main() and stores return value in temp 1.
// Does not return. (Enters infinite loop.)
function Sys.init 0
push constant 4000 // test THIS and THAT context save
pop pointer 0
push constant 5000
pop pointer 1
call Sys.main 0
pop temp 1
label LOOP
goto LOOP
// 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
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
// Sys.add12(int n)
//
// Returns n+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
+137
View File
@@ -0,0 +1,137 @@
(SimpleFunction.test)
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//DEFINEFUNC
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//DEFINEFUNC
@0
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@1
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@SP
A=M
A=A-1
M=!M
//NOT
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@1
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@SP
M=M-1
A=M
D=M
A=A-1
M=M-D
//SUB
@LCL
D=M
@R13
M=D
@5
D=A
@R13
D=M-D
A=D
D=M
@R14
M=D
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D
@R13
M=M-1
A=M
D=M
@THAT
M=D
@R13
M=M-1
A=M
D=M
@THIS
M=D
@R13
M=M-1
A=M
D=M
@ARG
M=D
@R13
M=M-1
A=M
D=M
@LCL
M=D
@R14
A=M
0;JMP
//RETURN
@@ -0,0 +1,2 @@
| RAM[0] | RAM[1] | RAM[2] | RAM[3] | RAM[4] |RAM[310]|
| 311 | 305 | 300 | 3010 | 4010 | 1196 |
@@ -0,0 +1,2 @@
| RAM[0] | RAM[1] | RAM[2] | RAM[3] | RAM[4] |RAM[310]|
| 311 | 305 | 300 | 3010 | 4010 | 1196 |
@@ -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/08/FunctionCalls/SimpleFunction/SimpleFunction.tst
load SimpleFunction.asm,
output-file SimpleFunction.out,
compare-to SimpleFunction.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[310]%D1.6.1;
set RAM[0] 317,
set RAM[1] 317,
set RAM[2] 310,
set RAM[3] 3000,
set RAM[4] 4000,
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;
}
output;
+16
View File
@@ -0,0 +1,16 @@
// 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/08/FunctionCalls/SimpleFunction/SimpleFunction.vm
// Performs a simple calculation and returns the result.
function SimpleFunction.test 2
push local 0
push local 1
add
not
push argument 0
add
push argument 1
sub
return
@@ -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/08/FunctionCalls/SimpleFunction/SimpleFunctionVME.tst
load SimpleFunction.vm,
output-file SimpleFunction.out,
compare-to SimpleFunction.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[310]%D1.6.1;
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;
}
output;
+20
View 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/08/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
View 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/08/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
+649
View File
@@ -0,0 +1,649 @@
@256
D=A
@SP
M=D
@MainLoopXYZRA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@0
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Sys.init
0;JMP
(MainLoopXYZRARA)
//CALLFUNC
(Sys.init)
@6
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@8
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@Class1.set5RA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@2
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Class1.set
0;JMP
(Class1.set5RA)
//CALLFUNC
@SP
M=M-1
A=M
D=M
@5
M=D
//pop TMP
@23
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@15
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@Class2.set6RA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@2
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Class2.set
0;JMP
(Class2.set6RA)
//CALLFUNC
@SP
M=M-1
A=M
D=M
@5
M=D
//pop TMP
@Class1.get7RA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@0
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Class1.get
0;JMP
(Class1.get7RA)
//CALLFUNC
@Class2.get8RA
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL
D=M
@SP
A=M
M=D
@SP
M=M+1
@ARG
D=M
@SP
A=M
M=D
@SP
M=M+1
@THIS
D=M
@SP
A=M
M=D
@SP
M=M+1
@THAT
D=M
@SP
A=M
M=D
@SP
M=M+1
@SP
D=M
@0
D=D-A
@5
D=D-A
@ARG
M=D
@SP
D=M
@LCL
M=D
@Class2.get
0;JMP
(Class2.get8RA)
//CALLFUNC
(Sys.init$WHILE)
//LABEL
@Sys.init$WHILE
0;JMP
//GOTO
(Class1.set)
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@SP
M=M-1
A=M
D=M
@Class1.0
M=D
//pop STATIC
@1
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@SP
M=M-1
A=M
D=M
@Class1.1
M=D
//pop STATIC
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@LCL
D=M
@R13
M=D
@5
D=A
@R13
D=M-D
A=D
D=M
@R14
M=D
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D
@R13
M=M-1
A=M
D=M
@THAT
M=D
@R13
M=M-1
A=M
D=M
@THIS
M=D
@R13
M=M-1
A=M
D=M
@ARG
M=D
@R13
M=M-1
A=M
D=M
@LCL
M=D
@R14
A=M
0;JMP
//RETURN
(Class1.get)
@Class1.0
D=M
@SP
A=M
M=D
@SP
M=M+1
//push STATIC
@Class1.1
D=M
@SP
A=M
M=D
@SP
M=M+1
//push STATIC
@SP
M=M-1
A=M
D=M
A=A-1
M=M-D
//SUB
@LCL
D=M
@R13
M=D
@5
D=A
@R13
D=M-D
A=D
D=M
@R14
M=D
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D
@R13
M=M-1
A=M
D=M
@THAT
M=D
@R13
M=M-1
A=M
D=M
@THIS
M=D
@R13
M=M-1
A=M
D=M
@ARG
M=D
@R13
M=M-1
A=M
D=M
@LCL
M=D
@R14
A=M
0;JMP
//RETURN
(Class2.set)
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@SP
M=M-1
A=M
D=M
@Class2.0
M=D
//pop STATIC
@1
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@SP
M=M-1
A=M
D=M
@Class2.1
M=D
//pop STATIC
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@LCL
D=M
@R13
M=D
@5
D=A
@R13
D=M-D
A=D
D=M
@R14
M=D
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D
@R13
M=M-1
A=M
D=M
@THAT
M=D
@R13
M=M-1
A=M
D=M
@THIS
M=D
@R13
M=M-1
A=M
D=M
@ARG
M=D
@R13
M=M-1
A=M
D=M
@LCL
M=D
@R14
A=M
0;JMP
//RETURN
(Class2.get)
@Class2.0
D=M
@SP
A=M
M=D
@SP
M=M+1
//push STATIC
@Class2.1
D=M
@SP
A=M
M=D
@SP
M=M+1
//push STATIC
@SP
M=M-1
A=M
D=M
A=A-1
M=M-D
//SUB
@LCL
D=M
@R13
M=D
@5
D=A
@R13
D=M-D
A=D
D=M
@R14
M=D
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D
@R13
M=M-1
A=M
D=M
@THAT
M=D
@R13
M=M-1
A=M
D=M
@THIS
M=D
@R13
M=M-1
A=M
D=M
@ARG
M=D
@R13
M=M-1
A=M
D=M
@LCL
M=D
@R14
A=M
0;JMP
//RETURN
+2
View File
@@ -0,0 +1,2 @@
| RAM[0] |RAM[261]|RAM[262]|
| 263 | -2 | 8 |
+2
View File
@@ -0,0 +1,2 @@
| RAM[0] |RAM[261]|RAM[262]|
| 263 | -2 | 8 |
+17
View File
@@ -0,0 +1,17 @@
// 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/08/FunctionCalls/StaticsTest/StaticsTest.tst
load StaticsTest.asm,
output-file StaticsTest.out,
compare-to StaticsTest.cmp,
output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1 RAM[262]%D1.6.1;
set RAM[0] 256,
repeat 2500 {
ticktock;
}
output;
+17
View File
@@ -0,0 +1,17 @@
// 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/08/FunctionCalls/StaticsTest/StaticsTestVME.tst
load, // loads all the VM files from the current directory.
output-file StaticsTest.out,
compare-to StaticsTest.cmp,
output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1 RAM[262]%D1.6.1;
set sp 261,
repeat 36 {
vmstep;
}
output;
+20
View 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/08/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 WHILE
goto WHILE
+142
View File
@@ -0,0 +1,142 @@
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@0
D=A
@LCL
M=M+D
@SP
M=M-1
A=M
D=M
@LCL
A=M
M=D
@0
D=A
@LCL
M=M-D
//pop LOCAL
(Sys.init$LOOP_START)
//LABEL
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@0
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@0
D=A
@LCL
M=M+D
@SP
M=M-1
A=M
D=M
@LCL
A=M
M=D
@0
D=A
@LCL
M=M-D
//pop LOCAL
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@1
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
A=A-1
M=M-D
//SUB
@0
D=A
@ARG
M=M+D
@SP
M=M-1
A=M
D=M
@ARG
A=M
M=D
@0
D=A
@ARG
M=M-D
//pop ARG
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@SP
M=M-1
A=M
D=M
@Sys.init$LOOP_START
D;JNE
//IFGOTO
@0
D=A
@LCL
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push LOCAL
+2
View File
@@ -0,0 +1,2 @@
| RAM[0] |RAM[256]|
| 257 | 6 |
+127
View File
@@ -0,0 +1,127 @@
0000000000000000
1110110000010000
0000000000000000
1111110000100000
1110001100001000
0000000000000000
1111110111001000
0000000000000000
1110110000010000
0000000000000001
1111000010001000
0000000000000000
1111110010001000
1111110000100000
1111110000010000
0000000000000001
1111110000100000
1110001100001000
0000000000000000
1110110000010000
0000000000000001
1111000111001000
0000000000000000
1110110000010000
0000000000000010
1111000010100000
1111110000010000
0000000000000000
1111110000100000
1110001100001000
0000000000000000
1111110111001000
0000000000000000
1110110000010000
0000000000000001
1111000010100000
1111110000010000
0000000000000000
1111110000100000
1110001100001000
0000000000000000
1111110111001000
0000000000000000
1111110010001000
1111110000100000
1111110000010000
1110110010100000
1111000010001000
0000000000000000
1110110000010000
0000000000000001
1111000010001000
0000000000000000
1111110010001000
1111110000100000
1111110000010000
0000000000000001
1111110000100000
1110001100001000
0000000000000000
1110110000010000
0000000000000001
1111000111001000
0000000000000000
1110110000010000
0000000000000010
1111000010100000
1111110000010000
0000000000000000
1111110000100000
1110001100001000
0000000000000000
1111110111001000
0000000000000001
1110110000010000
0000000000000000
1111110000100000
1110001100001000
0000000000000000
1111110111001000
0000000000000000
1111110010001000
1111110000100000
1111110000010000
1110110010100000
1111000111001000
0000000000000000
1110110000010000
0000000000000010
1111000010001000
0000000000000000
1111110010001000
1111110000100000
1111110000010000
0000000000000010
1111110000100000
1110001100001000
0000000000000000
1110110000010000
0000000000000010
1111000111001000
0000000000000000
1110110000010000
0000000000000010
1111000010100000
1111110000010000
0000000000000000
1111110000100000
1110001100001000
0000000000000000
1111110111001000
0000000000000000
1111110010001000
1111110000100000
1111110000010000
0000000000010110
1110001100000101
0000000000000000
1110110000010000
0000000000000001
1111000010100000
1111110000010000
0000000000000000
1111110000100000
1110001100001000
0000000000000000
1111110111001000
+2
View File
@@ -0,0 +1,2 @@
| RAM[0] |RAM[256]|
| 256 | 1 |
+20
View 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/08/ProgramFlow/BasicLoop/BasicLoop.tst
load BasicLoop.asm,
output-file BasicLoop.out,
compare-to BasicLoop.cmp,
output-list RAM[0]%D1.6.1 RAM[256]%D1.6.1;
set RAM[0] 256,
set RAM[1] 300,
set RAM[2] 400,
set RAM[400] 3,
repeat 600 {
ticktock;
}
output;
+22
View File
@@ -0,0 +1,22 @@
// 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/08/ProgramFlow/BasicLoop/BasicLoop.vm
// Computes the sum 1 + 2 + ... + argument[0] and pushes the
// result onto the stack. Argument[0] is initialized by the test
// script before this code starts running.
push constant 0
pop local 0 // initializes sum = 0
label LOOP_START
push argument 0
push local 0
add
pop local 0 // sum = sum + counter
push argument 0
push constant 1
sub
pop argument 0 // counter--
push argument 0
if-goto LOOP_START // If counter != 0, goto LOOP_START
push local 0
+20
View 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/08/ProgramFlow/BasicLoop/BasicLoopVME.tst
load BasicLoop.vm,
output-file BasicLoop.out,
compare-to BasicLoop.cmp,
output-list RAM[0]%D1.6.1 RAM[256]%D1.6.1;
set sp 256,
set local 300,
set argument 400,
set argument[0] 3,
repeat 33 {
vmstep;
}
output;
+255
View File
@@ -0,0 +1,255 @@
@1
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@SP
M=M-1
A=M
D=M
@4
M=D
//pop POINTER
@0
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@0
D=A
@THAT
M=M+D
@SP
M=M-1
A=M
D=M
@THAT
A=M
M=D
@0
D=A
@THAT
M=M-D
//pop THAT
@1
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@1
D=A
@THAT
M=M+D
@SP
M=M-1
A=M
D=M
@THAT
A=M
M=D
@1
D=A
@THAT
M=M-D
//pop THAT
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@2
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
A=A-1
M=M-D
//SUB
@0
D=A
@ARG
M=M+D
@SP
M=M-1
A=M
D=M
@ARG
A=M
M=D
@0
D=A
@ARG
M=M-D
//pop ARG
(Sys.init$MAIN_LOOP_START)
//LABEL
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@SP
M=M-1
A=M
D=M
@Sys.init$COMPUTE_ELEMENT
D;JNE
//IFGOTO
@Sys.init$END_PROGRAM
0;JMP
//GOTO
(Sys.init$COMPUTE_ELEMENT)
//LABEL
@0
D=A
@THAT
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push THAT
@1
D=A
@THAT
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push THAT
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@2
D=A
@THAT
M=M+D
@SP
M=M-1
A=M
D=M
@THAT
A=M
M=D
@2
D=A
@THAT
M=M-D
//pop THAT
@4
D=M
@SP
A=M
M=D
@SP
M=M+1
//push POINTER
@1
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
A=A-1
M=M+D
//ADD
@SP
M=M-1
A=M
D=M
@4
M=D
//pop POINTER
@0
D=A
@ARG
A=M+D
D=M
@SP
A=M
M=D
@SP
M=M+1
//push ARGUMENT
@1
D=A
@SP
A=M
M=D
@SP
M=M+1
//push CONSTANT
@SP
M=M-1
A=M
D=M
A=A-1
M=M-D
//SUB
@0
D=A
@ARG
M=M+D
@SP
M=M-1
A=M
D=M
@ARG
A=M
M=D
@0
D=A
@ARG
M=M-D
//pop ARG
@Sys.init$MAIN_LOOP_START
0;JMP
//GOTO
(Sys.init$END_PROGRAM)
//LABEL
@@ -0,0 +1,2 @@
|RAM[3000]|RAM[3001]|RAM[3002]|RAM[3003]|RAM[3004]|RAM[3005]|
| 0 | 1 | 1 | 2 | 3 | 5 |
@@ -0,0 +1,2 @@
|RAM[3000]|RAM[3001]|RAM[3002]|RAM[3003]|RAM[3004]|RAM[3005]|
| 0 | 1 | 1 | 2 | 3 | 5 |
@@ -0,0 +1,22 @@
// 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/08/ProgramFlow/FibonacciSeries/FibonacciSeries.tst
load FibonacciSeries.asm,
output-file FibonacciSeries.out,
compare-to FibonacciSeries.cmp,
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;
set RAM[0] 256,
set RAM[1] 300,
set RAM[2] 400,
set RAM[400] 6,
set RAM[401] 3000,
repeat 1100 {
ticktock;
}
output;
+49
View File
@@ -0,0 +1,49 @@
// 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/08/ProgramFlow/FibonacciSeries/FibonacciSeries.vm
// Puts the first argument[0] elements of the Fibonacci series
// in the memory, starting in the address given in argument[1].
// Argument[0] and argument[1] are initialized by the test script
// before this code starts running.
push argument 1
pop pointer 1 // that = argument[1]
push constant 0
pop that 0 // first element in the series = 0
push constant 1
pop that 1 // second element in the series = 1
push argument 0
push constant 2
sub
pop argument 0 // num_of_elements -= 2 (first 2 elements are set)
label MAIN_LOOP_START
push argument 0
if-goto COMPUTE_ELEMENT // if num_of_elements > 0, goto COMPUTE_ELEMENT
goto END_PROGRAM // otherwise, goto END_PROGRAM
label COMPUTE_ELEMENT
push that 0
push that 1
add
pop that 2 // that[2] = that[0] + that[1]
push pointer 1
push constant 1
add
pop pointer 1 // that += 1
push argument 0
push constant 1
sub
pop argument 0 // num_of_elements--
goto MAIN_LOOP_START
label END_PROGRAM
@@ -0,0 +1,22 @@
// 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/08/ProgramFlow/FibonacciSeries/FibonacciSeriesVME.tst
load FibonacciSeries.vm,
output-file FibonacciSeries.out,
compare-to FibonacciSeries.cmp,
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;
set sp 256,
set local 300,
set argument 400,
set argument[0] 6,
set argument[1] 3000,
repeat 73 {
vmstep;
}
output;
+246
View File
@@ -0,0 +1,246 @@
import os
from pathlib import Path
def clear_file(clearfile):
temp_string_cf = '' # clears the empty lines, comments and spaces and writes them in a string
for vmline in clearfile:
flag = 0
if vmline == '\n':
continue
for index in range(len(vmline)):
if vmline[index:index + 2] == '//':
if flag == 1:
temp_string_cf += '\n'
break
if flag == 1 and vmline[index:index + 2] == ' ':
temp_string_cf += '\n'
break
temp_string_cf += vmline[index]
flag = 1
return temp_string_cf
def push(pushline, funcname):
if 'this' in pushline:
number = int(pushline[10:])
pushline = '@' + str(number) + '\nD=A\n@THIS\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push THIS\n'
elif 'that' in pushline:
number = int(pushline[10:])
pushline = '@' + str(number) + '\nD=A\n@THAT\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push THAT\n'
elif 'temp' in pushline:
number = int(pushline[10:])
number += 5
pushline = '@' + str(number) + '\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push TMP\n'
elif 'local' in pushline:
number = int(pushline[11:])
pushline = '@' + str(number) + '\nD=A\n@LCL\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push LOCAL\n'
elif 'static' in pushline:
number = int(pushline[12:])
pushline = '@' + funcname + '.' + str(number) + '\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push STATIC\n'
elif 'pointer' in pushline:
number = int(pushline[13:])
number += 3
pushline = '@' + str(number) + '\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push POINTER\n'
elif 'argument' in pushline:
number = int(pushline[14:])
pushline = '@' + str(number) + '\nD=A\n@ARG\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push ARGUMENT\n'
elif 'constant' in pushline:
number = pushline[14:]
pushline = '@' + str(number) + '\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push CONSTANT\n'
return pushline
def pop(popline, funcname):
if 'this' in popline:
number = int(popline[9:])
popline = '@' + str(number) + '\nD=A\n@THIS\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@THIS\nA=M\nM=D\n' + '@' + str(
number) + '\nD=A\n@THIS\nM=M-D\n//pop THIS\n'
elif 'that' in popline:
number = int(popline[9:])
popline = '@' + str(number) + '\nD=A\n@THAT\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@THAT\nA=M\nM=D\n' + '@' + str(
number) + '\nD=A\n@THAT\nM=M-D\n//pop THAT\n'
elif 'temp' in popline:
number = int(popline[9:])
number = number + 5
popline = '@SP\nM=M-1\nA=M\nD=M\n@' + str(number) + '\nM=D\n//pop TMP\n'
elif 'local' in popline:
number = int(popline[10:])
popline = '@' + str(number) + '\nD=A\n@LCL\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@LCL\nA=M\nM=D\n' + '@' + str(
number) + '\nD=A\n@LCL\nM=M-D\n//pop LOCAL\n'
elif 'static' in popline:
number = int(popline[11:])
popline = '@SP\nM=M-1\nA=M\nD=M\n@' + funcname + '.' + str(number) + '\nM=D\n//pop STATIC\n'
elif 'pointer' in popline:
number = int(popline[12:])
number = number + 3
popline = '@SP\nM=M-1\nA=M\nD=M\n@' + str(number) + '\nM=D\n//pop POINTER\n'
elif 'argument' in popline:
number = int(popline[13:])
popline = '@' + str(number) + '\nD=A\n@ARG\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@ARG\nA=M\nM=D\n' + '@' + str(
number) + '\nD=A\n@ARG\nM=M-D\n//pop ARG\n'
return popline
def aritmetic(armline):
global trueCounter
global falseCounter
if armline == 'add':
armline = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M+D\n//ADD\n"
elif armline == 'sub':
armline = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M-D\n//SUB\n"
elif armline == 'neg':
armline = "@SP\nA=M\nA=A-1\nM=-M\n//NEG\n"
elif armline == 'eq':
armline = '@SP\nM=M-1\nA=M\nD=M\nA=A-1\nD=M-D\n@TRUE' + str(
trueCounter) + '\nD;JEQ\n@SP\nA=M\nA=A-1\nM=0\n@FALSE' + str(
falseCounter) + '\n0;JMP\n(TRUE' + str(trueCounter) + ')\n@SP\nA=M\nA=A-1\nM=-1\n(FALSE' + str(
falseCounter) + ')\n//EQ\n'
trueCounter += 1
falseCounter += 1
elif armline == 'gt':
armline = '@SP\nM=M-1\nA=M\nD=M\nA=A-1\nD=M-D\n@TRUE' + str(
trueCounter) + '\nD;JGT\n@SP\nA=M\nA=A-1\nM=0\n@FALSE' + str(
falseCounter) + '\n0;JMP\n(TRUE' + str(trueCounter) + ')\n@SP\nA=M\nA=A-1\nM=-1\n(FALSE' + str(
falseCounter) + ')\n//GT\n'
trueCounter += 1
falseCounter += 1
elif armline == 'lt':
armline = '@SP\nM=M-1\nA=M\nD=M\nA=A-1\nD=M-D\n@TRUE' + str(
trueCounter) + '\nD;JLT\n@SP\nA=M\nA=A-1\nM=0\n@FALSE' + str(
falseCounter) + '\n0;JMP\n(TRUE' + str(trueCounter) + ')\n@SP\nA=M\nA=A-1\nM=-1\n(FALSE' + str(
falseCounter) + ')\n//LT\n'
trueCounter += 1
falseCounter += 1
elif armline == 'and':
armline = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M&D\n//AND\n"
elif armline == 'or':
armline = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M|D\n//OR\n"
elif armline == 'not':
armline = "@SP\nA=M\nA=A-1\nM=!M\n//NOT\n"
return armline
def label(labelline):
labelline = '(' + func_label_name + '$' + labelline[6:] + ')\n//LABEL\n'
return labelline
def goto(gotoline):
gotoline = '@' + func_label_name + '$' + gotoline[5:] + '\n0;JMP\n//GOTO\n'
return gotoline
def if_goto(ifline):
ifline = '@SP\nM=M-1\nA=M\nD=M\n@' + func_label_name + '$' + ifline[8:] + '\nD;JNE\n//IFGOTO\n'
return ifline
def define_func(funcline):
global func_label_name
def_func_list = funcline.rsplit(' ')
func_label_name = def_func_list[1]
funcline = '(' + def_func_list[1] + ')\n'
for ind in range(int(def_func_list[2])):
funcline += '@0\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//DEFINEFUNC\n'
return funcline
def call_func(callline):
global f
call_func_list = callline.rsplit(' ')
callline = '@' + call_func_list[1] + str(f) + 'RA\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
callline += '@LCL\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
callline += '@ARG\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
callline += '@THIS\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
callline += '@THAT\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
callline += '@SP\nD=M\n@' + call_func_list[2] + '\nD=D-A\n@5\nD=D-A\n@ARG\nM=D\n'
callline += '@SP\nD=M\n@LCL\nM=D\n'
callline += '@' + call_func_list[1] + '\n0;JMP\n'
callline += '(' + call_func_list[1] + str(f) + 'RA)\n//CALLFUNC\n'
f += 1
return callline
def return_func(returnline):
returnline = '@LCL\nD=M\n@R13\nM=D\n'
returnline += '@5\nD=A\n@R13\nD=M-D\nA=D\nD=M\n@R14\nM=D\n'
returnline += '@SP\nA=M-1\nD=M\n@ARG\nA=M\nM=D\n'
returnline += '@ARG\nD=M+1\n@SP\nM=D\n'
returnline += '@R13\nM=M-1\nA=M\nD=M\n@THAT\nM=D\n'
returnline += '@R13\nM=M-1\nA=M\nD=M\n@THIS\nM=D\n'
returnline += '@R13\nM=M-1\nA=M\nD=M\n@ARG\nM=D\n'
returnline += '@R13\nM=M-1\nA=M\nD=M\n@LCL\nM=D\n'
returnline += '@R14\nA=M\n0;JMP\n//RETURN\n'
return returnline
def iterate(name_iterate, yourpath_iterate):
line = ''
new_string = ''
with open(Path(yourpath_iterate, name_iterate + '.vm'), "r+") as vmfile:
string_iterate = clear_file(vmfile)
for j in string_iterate: # zapisva liniqta v string koito posle se obrabotva
if j != '\n':
line += j
else:
if line[:4] == 'push':
new_string += push(line, name_iterate)
line = ''
elif line[:3] == 'pop':
new_string += pop(line, name_iterate)
line = ''
elif line[:2] in aritmeticList2 or line[:3] in aritmeticList3:
new_string += aritmetic(line)
line = ''
elif line[:5] == 'label':
new_string += label(line)
line = ''
elif line[:4] == 'goto':
new_string += goto(line)
line = ''
elif line[:7] == 'if-goto':
new_string += if_goto(line)
line = ''
elif line[:8] == 'function':
new_string += define_func(line)
line = ''
elif line[:4] == 'call':
new_string += call_func(line)
line = ''
elif line[:6] == 'return':
new_string += return_func(line)
line = ''
return new_string
trueCounter = falseCounter = f = 0
staticCounter = 16
func_label_name = ''
aritmeticList3 = ['add', 'sub', 'neg', 'and', 'not']
aritmeticList2 = ['or', 'gt', 'lt', 'eq']
yourpath = os.getcwd()
bootstrap = '''@256\nD=A\n@SP\nM=D\n@MainLoopXYZRA\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n@LCL\nD=M\n@SP\nA=M\nM=D\n@SP
M=M+1\n@ARG\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n@THIS\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n@THAT\nD=M\n@SP\nA=M\nM=D\n@SP
M=M+1\n@SP\nD=M\n@0\nD=D-A\n@5\nD=D-A\n@ARG\nM=D\n@SP\nD=M\n@LCL\nM=D\n@Sys.init\n0;JMP\n(MainLoopXYZRARA)
//CALLFUNC\n'''
for root, dirs, files in os.walk(yourpath, topdown=False):
nameslist = []
sysstring, functstring = '', ''
for name in files:
tempString = ''
if name[-3:] == '.vm':
nameslist += [name[:-3]]
for i in nameslist:
if i == 'Sys':
sysstring = bootstrap
sysstring += iterate(i, root)
else:
functstring += iterate(i, root)
if nameslist:
with open(Path(root, f'{os.path.split(root)[1]}.asm'), 'w+') as newfile:
newfile.write(sysstring + functstring)
+253
View File
@@ -0,0 +1,253 @@
import os
def clear_file(clearfile):
temp_string_cf = '' # clears the empty lines, comments and spaces and writes them in a string
for vmline in clearfile:
flag = 0
if vmline == '\n':
continue
for index in range(len(vmline)):
if vmline[index:index + 2] == '//':
if flag == 1:
temp_string_cf += '\n'
break
if flag == 1 and vmline[index:index + 2] == ' ':
temp_string_cf += '\n'
break
temp_string_cf += vmline[index]
flag = 1
return temp_string_cf
def push(pushline, funcname):
if 'this' in pushline:
number = int(pushline[10:])
pushline = '@' + str(number) + '\nD=A\n@THIS\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push THIS\n'
elif 'that' in pushline:
number = int(pushline[10:])
pushline = '@' + str(number) + '\nD=A\n@THAT\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push THAT\n'
elif 'temp' in pushline:
number = int(pushline[10:])
number += 5
pushline = '@' + str(number) + '\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push TMP\n'
elif 'local' in pushline:
number = int(pushline[11:])
pushline = '@' + str(number) + '\nD=A\n@LCL\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push LOCAL\n'
elif 'static' in pushline:
breakpoint()
number = int(pushline[12:])
pushline = '@' + funcname + '.' + str(number) + '\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push STATIC\n'
elif 'pointer' in pushline:
number = int(pushline[13:])
number += 3
pushline = '@' + str(number) + '\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push POINTER\n'
elif 'argument' in pushline:
number = int(pushline[14:])
pushline = '@' + str(number) + '\nD=A\n@ARG\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push ARGUMENT\n'
elif 'constant' in pushline:
number = pushline[14:]
pushline = '@' + str(number) + '\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push CONSTANT\n'
return pushline
def pop(popline, funcname):
if 'this' in popline:
number = int(popline[9:])
popline = '@' + str(number) + '\nD=A\n@THIS\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@THIS\nA=M\nM=D\n' + '@' + str(
number) + '\nD=A\n@THIS\nM=M-D\n//pop THIS\n'
elif 'that' in popline:
number = int(popline[9:])
popline = '@' + str(number) + '\nD=A\n@THAT\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@THAT\nA=M\nM=D\n' + '@' + str(
number) + '\nD=A\n@THAT\nM=M-D\n//pop THAT\n'
elif 'temp' in popline:
number = int(popline[9:])
number = number + 5
popline = '@SP\nM=M-1\nA=M\nD=M\n@' + str(number) + '\nM=D\n//pop TMP\n'
elif 'local' in popline:
number = int(popline[10:])
popline = '@' + str(number) + '\nD=A\n@LCL\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@LCL\nA=M\nM=D\n' + '@' + str(
number) + '\nD=A\n@LCL\nM=M-D\n//pop LOCAL\n'
elif 'static' in popline:
breakpoint()
number = int(popline[11:])
popline = '@SP\nM=M-1\nA=M\nD=M\n@' + funcname + '.' + str(number) + '\nM=D\n//pop STATIC\n'
elif 'pointer' in popline:
number = int(popline[12:])
number = number + 3
popline = '@SP\nM=M-1\nA=M\nD=M\n@' + str(number) + '\nM=D\n//pop POINTER\n'
elif 'argument' in popline:
number = int(popline[13:])
popline = '@' + str(number) + '\nD=A\n@ARG\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@ARG\nA=M\nM=D\n' + '@' + str(
number) + '\nD=A\n@ARG\nM=M-D\n//pop ARG\n'
return popline
def aritmetic(armline):
global trueCounter
global falseCounter
if armline == 'add':
armline = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M+D\n//ADD\n"
elif armline == 'sub':
armline = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M-D\n//SUB\n"
elif armline == 'neg':
armline = "@SP\nA=M\nA=A-1\nM=-M\n//NEG\n"
elif armline == 'eq':
armline = '@SP\nM=M-1\nA=M\nD=M\nA=A-1\nD=M-D\n@TRUE' + str(
trueCounter) + '\nD;JEQ\n@SP\nA=M\nA=A-1\nM=0\n@FALSE' + str(
falseCounter) + '\n0;JMP\n(TRUE' + str(trueCounter) + ')\n@SP\nA=M\nA=A-1\nM=-1\n(FALSE' + str(
falseCounter) + ')\n//EQ\n'
trueCounter += 1
falseCounter += 1
elif armline == 'gt':
armline = '@SP\nM=M-1\nA=M\nD=M\nA=A-1\nD=M-D\n@TRUE' + str(
trueCounter) + '\nD;JGT\n@SP\nA=M\nA=A-1\nM=0\n@FALSE' + str(
falseCounter) + '\n0;JMP\n(TRUE' + str(trueCounter) + ')\n@SP\nA=M\nA=A-1\nM=-1\n(FALSE' + str(
falseCounter) + ')\n//GT\n'
trueCounter += 1
falseCounter += 1
elif armline == 'lt':
armline = '@SP\nM=M-1\nA=M\nD=M\nA=A-1\nD=M-D\n@TRUE' + str(
trueCounter) + '\nD;JLT\n@SP\nA=M\nA=A-1\nM=0\n@FALSE' + str(
falseCounter) + '\n0;JMP\n(TRUE' + str(trueCounter) + ')\n@SP\nA=M\nA=A-1\nM=-1\n(FALSE' + str(
falseCounter) + ')\n//LT\n'
trueCounter += 1
falseCounter += 1
elif armline == 'and':
armline = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M&D\n//AND\n"
elif armline == 'or':
armline = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M|D\n//OR\n"
elif armline == 'not':
armline = "@SP\nA=M\nA=A-1\nM=!M\n//NOT\n"
return armline
def label(labelline):
labelline = '(' + func_label_name + '$' + labelline[6:] + ')\n//LABEL\n'
return labelline
def goto(gotoline):
gotoline = '@' + func_label_name + '$' + gotoline[5:] + '\n0;JMP\n//GOTO\n'
return gotoline
def if_goto(ifline):
ifline = '@SP\nM=M-1\nA=M\nD=M\n@' + func_label_name + '$' + ifline[8:] + '\nD;JNE\n//IFGOTO\n'
return ifline
def define_func(funcline):
global func_label_name
def_func_list = funcline.rsplit(' ')
func_label_name = def_func_list[1]
funcline = '(' + def_func_list[1] + ')\n'
for ind in range(int(def_func_list[2])):
funcline += '@0\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//DEFINEFUNC\n'
return funcline
def call_func(callline):
global f
call_func_list = callline.rsplit(' ')
callline = '@' + call_func_list[1] + str(f) + 'RA\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
callline += '@LCL\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
callline += '@ARG\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
callline += '@THIS\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
callline += '@THAT\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
callline += '@SP\nD=M\n@' + call_func_list[2] + '\nD=D-A\n@5\nD=D-A\n@ARG\nM=D\n'
callline += '@SP\nD=M\n@LCL\nM=D\n'
callline += '@' + call_func_list[1] + '\n0;JMP\n'
callline += '(' + call_func_list[1] + str(f) + 'RA)\n//CALLFUNC\n'
f += 1
return callline
def return_func(returnline):
returnline = '@LCL\nD=M\n@R13\nM=D\n'
returnline += '@5\nD=A\n@R13\nD=M-D\nA=D\nD=M\n@R14\nM=D\n'
returnline += '@SP\nA=M-1\nD=M\n@ARG\nA=M\nM=D\n'
returnline += '@ARG\nD=M+1\n@SP\nM=D\n'
returnline += '@R13\nM=M-1\nA=M\nD=M\n@THAT\nM=D\n'
returnline += '@R13\nM=M-1\nA=M\nD=M\n@THIS\nM=D\n'
returnline += '@R13\nM=M-1\nA=M\nD=M\n@ARG\nM=D\n'
returnline += '@R13\nM=M-1\nA=M\nD=M\n@LCL\nM=D\n'
returnline += '@R14\nA=M\n0;JMP\n//RETURN\n'
return returnline
def iterate(name_iterate, yourpath_iterate):
line = ''
new_string = ''
with open(yourpath_iterate + '/' + name_iterate + '.vm', "r+") as vmfile:
string_iterate = clear_file(vmfile)
print(string_iterate)
for j in string_iterate: # zapisva liniqta v string koito posle se obrabotva
if j != '\n':
line += j
else:
if line[:4] == 'push':
new_string += push(line, name_iterate)
line = ''
elif line[:3] == 'pop':
new_string += pop(line, name_iterate)
line = ''
elif line[:2] in aritmeticList2 or line[:3] in aritmeticList3:
new_string += aritmetic(line)
line = ''
elif line[:5] == 'label':
new_string += label(line)
line = ''
elif line[:4] == 'goto':
new_string += goto(line)
line = ''
elif line[:7] == 'if-goto':
new_string += if_goto(line)
line = ''
elif line[:8] == 'function':
new_string += define_func(line)
line = ''
elif line[:4] == 'call':
new_string += call_func(line)
line = ''
elif line[:6] == 'return':
new_string += return_func(line)
line = ''
return new_string
trueCounter = 0
falseCounter = 0
staticCounter = 16
f = 0
func_label_name = ''
aritmeticList3 = ['add', 'sub', 'neg', 'and', 'not']
aritmeticList2 = ['or', 'gt', 'lt', 'eq']
yourpath = 'C:/Users/SQA-AGrudev/Desktop/nand2tetris/projects/08/FunctionCalls/NestedCall'
folder_name = ''
for c in reversed(yourpath):
if c != '/':
folder_name += c
else:
break
folder_name = folder_name[::-1]
nameslist = []
for root, dirs, files in os.walk(yourpath, topdown=False):
for name in files:
tempString = ''
if name[-3:] == '.vm':
nameslist += [name[:-3]]
sysstring, functstring = '', ''
for i in nameslist:
if i == 'Sys':
sysstring = iterate(i, yourpath)
else:
functstring += iterate(i, yourpath)
tempString1 ='@256\nD=A\n@SP\nM=D\n@Sys.init\n0;JMP\n'+ sysstring + functstring
with open(yourpath + '/' + folder_name + '.asm', 'w+') as newfile: # tva tqbva da se kazva papkata ne faila
# TODO before i write the whole things i think i should write SP=256 call Sys.init in assembler pretty sure i should
newfile.write(tempString1)
# TODO make it run more than 1 file
+2
View File
@@ -0,0 +1,2 @@
python3
debug