[08] Implement Return/Function/Init
Return isn't functional (yet) Init isn't called (yet)
This commit is contained in:
parent
2fbdba0cf2
commit
b052ab617c
|
@ -0,0 +1,98 @@
|
|||
(SimpleFunction.test) // function SimpleFunction.test 2
|
||||
@SP
|
||||
A=M
|
||||
M=D
|
||||
@SP
|
||||
M=M+1
|
||||
@SP
|
||||
A=M
|
||||
M=D
|
||||
@SP
|
||||
M=M+1
|
||||
@LCL
|
||||
A=M
|
||||
D=M
|
||||
@SP
|
||||
A=M
|
||||
M=D
|
||||
@SP
|
||||
M=M+1 // end push local 0 (L1)
|
||||
@LCL // local 1
|
||||
D=M
|
||||
@1 // write 1 to A
|
||||
D=D+A // D = segment+index
|
||||
@R13 // save it to R13
|
||||
M=D // write @LCL+1 to R13
|
||||
@R13
|
||||
A=M
|
||||
D=M
|
||||
@SP
|
||||
A=M
|
||||
M=D
|
||||
@SP
|
||||
M=M+1 // end push local 1 (L2)
|
||||
@SP // ==== add ====
|
||||
A=M-1
|
||||
D=M
|
||||
A=A-1
|
||||
M=D+M
|
||||
@SP
|
||||
M=M-1 // end add (L3)
|
||||
@SP // ==== not ====
|
||||
A=M-1
|
||||
D=M
|
||||
M=!M // end not (L4)
|
||||
@ARG
|
||||
A=M
|
||||
D=M
|
||||
@SP
|
||||
A=M
|
||||
M=D
|
||||
@SP
|
||||
M=M+1 // end push argument 0 (L5)
|
||||
@SP // ==== add ====
|
||||
A=M-1
|
||||
D=M
|
||||
A=A-1
|
||||
M=D+M
|
||||
@SP
|
||||
M=M-1 // end add (L6)
|
||||
@ARG // argument 1
|
||||
D=M
|
||||
@1 // write 1 to A
|
||||
D=D+A // D = segment+index
|
||||
@R13 // save it to R13
|
||||
M=D // write @ARG+1 to R13
|
||||
@R13
|
||||
A=M
|
||||
D=M
|
||||
@SP
|
||||
A=M
|
||||
M=D
|
||||
@SP
|
||||
M=M+1 // end push argument 1 (L7)
|
||||
@SP // ==== sub ====
|
||||
A=M-1
|
||||
D=M
|
||||
A=A-1
|
||||
M=M-D
|
||||
@SP
|
||||
M=M-1 // end sub (L8)
|
||||
@ARG
|
||||
D=M+1
|
||||
@SP
|
||||
M=D // @SP = ARG+1
|
||||
@LCL
|
||||
D=M // D=@LCL
|
||||
@THAT
|
||||
MD=D-1 // THAT = LCL-1
|
||||
@THIS
|
||||
MD=D-1 // THIS = LCL-2
|
||||
@ARG
|
||||
MD=D-1 // ARG = LCL-3
|
||||
@LCL
|
||||
MD=D-1 // LCL = LCL-4
|
||||
A=D-1 // A = LCL-5
|
||||
0;JMP // Jump to *(LCL-5)
|
||||
@97
|
||||
0;JMP
|
|
@ -0,0 +1 @@
|
|||
| RAM[0] | RAM[1] | RAM[2] | RAM[3] | RAM[4] |RAM[310]|
|
|
@ -1,2 +0,0 @@
|
|||
|RAM[3000]|RAM[3001]|RAM[3002]|RAM[3003]|RAM[3004]|RAM[3005]|
|
||||
| 0 | 1 | 1 | 2 | 3 | 5 |
|
|
@ -12,6 +12,68 @@ class CodeWriter {
|
|||
$this->fn = null;
|
||||
}
|
||||
|
||||
public function writeReturn() {
|
||||
$this->write([
|
||||
// SP=ARG+1
|
||||
"@ARG",
|
||||
"D=M+1",
|
||||
"@SP",
|
||||
"M=D // @SP = ARG+1",
|
||||
// THAT = LCL-1
|
||||
"@LCL",
|
||||
"D=M // D=@LCL",
|
||||
"@THAT",
|
||||
"MD=D-1 // THAT = LCL-1",
|
||||
// THIS = LCL-2
|
||||
"@THIS",
|
||||
"MD=D-1 // THIS = LCL-2",
|
||||
// ARG = LCL-3
|
||||
"@ARG",
|
||||
"MD=D-1 // ARG = LCL-3",
|
||||
// LCL = LCL-4
|
||||
"@LCL",
|
||||
"MD=D-1 // LCL = LCL-4",
|
||||
"A=D-1 // A = LCL-5",
|
||||
"0;JMP // Jump to *(LCL-5)",
|
||||
]);
|
||||
}
|
||||
|
||||
public function writeFunction($name, $numArgs) {
|
||||
$this->fn = $name;
|
||||
$this->write([
|
||||
"($name) // function $name $numArgs",
|
||||
]);
|
||||
for($i=0;$i<$numArgs;$i++) {
|
||||
$this->write([
|
||||
"@SP",
|
||||
"A=M",
|
||||
"M=D",
|
||||
"@SP",
|
||||
"M=M+1"
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the preable to initialize the VM
|
||||
*/
|
||||
private function writeInit() {
|
||||
$this->write([
|
||||
"@256",
|
||||
"D=A",
|
||||
"@SP",
|
||||
"M=D // initialized SP to 256",
|
||||
"@16000",
|
||||
"D=A",
|
||||
"@LCL",
|
||||
"M=D // initialized @LCL to 16000",
|
||||
"@16500",
|
||||
"D=A",
|
||||
"@ARG",
|
||||
"M=D // initialized @ARG to 16500",
|
||||
]);
|
||||
}
|
||||
|
||||
function setInputFileName($inputFileName) {
|
||||
$this->vm = basename($inputFileName, ".vm");
|
||||
}
|
||||
|
|
|
@ -5,10 +5,12 @@ namespace captn3m0\NandToTetris;
|
|||
class CommandType {
|
||||
const PUSH = 1;
|
||||
const POP = 2;
|
||||
|
||||
// Program Flow Commands
|
||||
const LABEL= 3;
|
||||
const GOTO= 4;
|
||||
const IF= 5;
|
||||
|
||||
// Function Calling Commands
|
||||
const FUNC= 6;
|
||||
const RETURN= 7;
|
||||
|
|
|
@ -21,6 +21,10 @@ class VMTranslator {
|
|||
$this->writer = new CodeWriter($outputFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main entry point for the VM Translator
|
||||
* and starts the translate sequence
|
||||
*/
|
||||
function translate() {
|
||||
foreach ($this->files as $file) {
|
||||
$parser = new Parser($file);
|
||||
|
@ -55,6 +59,16 @@ class VMTranslator {
|
|||
$this->writer->writeGoto($label);
|
||||
break;
|
||||
|
||||
case CommandType::FUNC:
|
||||
$functionName = $parser->arg1();
|
||||
$numberOfArgs = $parser->arg2();
|
||||
$this->writer->writeFunction($functionName, $numberOfArgs);
|
||||
break;
|
||||
|
||||
case CommandType::RETURN:
|
||||
$this->writer->writeReturn();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \Exception("Not Implemented $command", 1);
|
||||
break;
|
||||
|
@ -66,6 +80,10 @@ class VMTranslator {
|
|||
$this->writer->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an output file name
|
||||
* for the VM. Same as the Directory.asm
|
||||
*/
|
||||
private function outputFile() {
|
||||
$dir = dirname($this->files[0]);
|
||||
$name = basename($dir);
|
||||
|
|
Loading…
Reference in New Issue