[08] Implemented call, but it is breaking somewhere

This commit is contained in:
Nemo 2020-06-04 02:03:46 +05:30
parent 5160559eff
commit 4fdc98bb72
5 changed files with 452 additions and 1 deletions

View File

@ -0,0 +1,370 @@
@256 // init starts
D=A
@SP
M=D // initialized SP to 256
@300
D=A
@LCL
M=D // initialized @LCL to 300
@400
D=A
@ARG
M=D // initialized @ARG to 400, init ends
@Sys.init
0;JMP
(Main.fibonacci) // function Main.fibonacci 0
@ARG
A=M
D=M
@SP
A=M
M=D
@SP
M=M+1 // end push argument 0 (L1)
@2 // push constant 2
D=A
@SP
A=M
M=D
@SP
M=M+1 // end push constant 2 (L2)
@SP // ==== lt ====
A=M-1
D=M
A=A-1
D=M-D
M=0
M=M-1
@43
D;JLT
@SP
A=M-1
A=A-1
M=0
@SP
M=M-1 // end lt (L3)
@SP
AM=M-1
D=M
@Main.fibonacciIF_TRUE
D;JNE // end if-goto IF_TRUE (L4)
@Main.fibonacciIF_FALSE
0;JMP // end goto IF_FALSE (L5)
(Main.fibonacciIF_TRUE) // end label IF_TRUE (L6)
@ARG
A=M
D=M
@SP
A=M
M=D
@SP
M=M+1 // end push argument 0 (L7)
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D // @SP = ARG+1
@LCL
D=M
@R13
M=D // Save LCL to R13
A=D-1 // A=*LCL-1
D=M // D=*(*LCL-1)
@THAT // A=THAT
M=D // *that = *(*lcl-1)
@R13
A=M-1
A=A-1 // A=*LCL-2
D=M // D=*(*LCL-2)
@THIS // A=THIS
M=D // *THIS = *(*lcl-2)
@R13
A=M-1
A=A-1
A=A-1 // A=*LCL-3
D=M // D=*(*LCL-3)
@ARG // A=ARG
M=D // *ARG = *(*lcl-3)
@R13
A=M-1
A=A-1
A=A-1
A=A-1 // A=*LCL-4
D=M // D=*(*LCL-4)
@LCL // A=LCL
M=D // *LCL = *(*lcl-4)
@R13
A=M-1
A=A-1
A=A-1
A=A-1
A=A-1 // A=*LCL-5
A=M // A=*(*LCL-5)
0;JMP // Jump to *(LCL-5)
(Main.fibonacciIF_FALSE) // end label IF_FALSE (L9)
@ARG
A=M
D=M
@SP
A=M
M=D
@SP
M=M+1 // end push argument 0 (L10)
@2 // push constant 2
D=A
@SP
A=M
M=D
@SP
M=M+1 // end push constant 2 (L11)
@SP // ==== sub ====
A=M-1
D=M
A=A-1
M=M-D
@SP
M=M-1 // end sub (L12)
@5fd25fdab54b4bfd5a91536ecfd6806e
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL // Read @LCL to A
D=M // Put @LCL to D
@SP
A=M
M=D // Save @LCL to SP
@SP
M=M+1
@ARG // Read @ARG to A
D=M // Put @ARG to D
@SP
A=M
M=D // Save @ARG to SP
@SP
M=M+1
@THIS // Read @THIS to A
D=M // Put @THIS to D
@SP
A=M
M=D // Save @THIS to SP
@SP
M=M+1
@THAT // Read @THAT to A
D=M // Put @THAT to D
@SP
A=M
M=D // Save @THAT to SP
@SP
M=M+1
@SP
D=M
@LCL
M=D
D=D-1
D=D-1
D=D-1
D=D-1
D=D-1
D=D-1
@ARG
M=D
@Main.fibonacci // Jump to Main.fibonacci
0;JMP
(5fd25fdab54b4bfd5a91536ecfd6806e) // return back from function here
@ARG
A=M
D=M
@SP
A=M
M=D
@SP
M=M+1 // end push argument 0 (L14)
@1 // push constant 1
D=A
@SP
A=M
M=D
@SP
M=M+1 // end push constant 1 (L15)
@SP // ==== sub ====
A=M-1
D=M
A=A-1
M=M-D
@SP
M=M-1 // end sub (L16)
@a954c9cff71cdccc09f4338e60df6394
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL // Read @LCL to A
D=M // Put @LCL to D
@SP
A=M
M=D // Save @LCL to SP
@SP
M=M+1
@ARG // Read @ARG to A
D=M // Put @ARG to D
@SP
A=M
M=D // Save @ARG to SP
@SP
M=M+1
@THIS // Read @THIS to A
D=M // Put @THIS to D
@SP
A=M
M=D // Save @THIS to SP
@SP
M=M+1
@THAT // Read @THAT to A
D=M // Put @THAT to D
@SP
A=M
M=D // Save @THAT to SP
@SP
M=M+1
@SP
D=M
@LCL
M=D
D=D-1
D=D-1
D=D-1
D=D-1
D=D-1
D=D-1
@ARG
M=D
@Main.fibonacci // Jump to Main.fibonacci
0;JMP
(a954c9cff71cdccc09f4338e60df6394) // return back from function here
@SP // ==== add ====
A=M-1
D=M
A=A-1
M=D+M
@SP
M=M-1 // end add (L18)
@SP
A=M-1
D=M
@ARG
A=M
M=D
@ARG
D=M+1
@SP
M=D // @SP = ARG+1
@LCL
D=M
@R13
M=D // Save LCL to R13
A=D-1 // A=*LCL-1
D=M // D=*(*LCL-1)
@THAT // A=THAT
M=D // *that = *(*lcl-1)
@R13
A=M-1
A=A-1 // A=*LCL-2
D=M // D=*(*LCL-2)
@THIS // A=THIS
M=D // *THIS = *(*lcl-2)
@R13
A=M-1
A=A-1
A=A-1 // A=*LCL-3
D=M // D=*(*LCL-3)
@ARG // A=ARG
M=D // *ARG = *(*lcl-3)
@R13
A=M-1
A=A-1
A=A-1
A=A-1 // A=*LCL-4
D=M // D=*(*LCL-4)
@LCL // A=LCL
M=D // *LCL = *(*lcl-4)
@R13
A=M-1
A=A-1
A=A-1
A=A-1
A=A-1 // A=*LCL-5
A=M // A=*(*LCL-5)
0;JMP // Jump to *(LCL-5)
(Sys.init) // function Sys.init 0
@4 // push constant 4
D=A
@SP
A=M
M=D
@SP
M=M+1 // end push constant 4 (L21)
@dd19df789547baebfea110998cdf5713
D=A
@SP
A=M
M=D
@SP
M=M+1
@LCL // Read @LCL to A
D=M // Put @LCL to D
@SP
A=M
M=D // Save @LCL to SP
@SP
M=M+1
@ARG // Read @ARG to A
D=M // Put @ARG to D
@SP
A=M
M=D // Save @ARG to SP
@SP
M=M+1
@THIS // Read @THIS to A
D=M // Put @THIS to D
@SP
A=M
M=D // Save @THIS to SP
@SP
M=M+1
@THAT // Read @THAT to A
D=M // Put @THAT to D
@SP
A=M
M=D // Save @THAT to SP
@SP
M=M+1
@SP
D=M
@LCL
M=D
D=D-1
D=D-1
D=D-1
D=D-1
D=D-1
D=D-1
@ARG
M=D
@Main.fibonacci // Jump to Main.fibonacci
0;JMP
(dd19df789547baebfea110998cdf5713) // return back from function here
(Sys.initWHILE) // end label WHILE (L23)
@Sys.initWHILE
0;JMP // end goto WHILE (L24)
@369
0;JMP

View File

@ -0,0 +1,2 @@
| RAM[0] |RAM[261]|
| 257 | 0 |

View File

@ -10,6 +10,8 @@ M=D // initialized @LCL to 300
D=A
@ARG
M=D // initialized @ARG to 400, init ends
@Sys.init
0;JMP
@ARG // argument 1
D=M
@1 // write 1 to A
@ -204,5 +206,5 @@ M=D // end pop argument 0 (L26)
@__GLOBAL__.MAIN_LOOP_START
0;JMP // end goto MAIN_LOOP_START (L27)
(__GLOBAL__.END_PROGRAM) // end label END_PROGRAM (L28)
@207
@209
0;JMP

View File

@ -112,6 +112,77 @@ class CodeWriter {
}
}
/**
* Function call executed, save state and JUMP
*/
public function writeCall(String $functionName, $numArgs) {
$label = bin2hex(random_bytes(16));
// push the label to top of the stack
$this->write([
"@$label",
"D=A",
"@SP",
"A=M",
"M=D",
"@SP",
"M=M+1"
]);
$pushes = [
"@LCL",
"@ARG",
"@THIS",
"@THAT",
];
// TODO: optimize this by saving LCL, ARG
// then doing the SP-n-5 calculation (since that will be much faster)
// and then updating ARG
foreach ($pushes as $lookupRegister) {
$this->write([
"$lookupRegister // Read $lookupRegister to A",
"D=M // Put $lookupRegister to D",
"@SP",
"A=M",
"M=D // Save $lookupRegister to SP",
"@SP",
"M=M+1",
]);
}
// Load current stackpointer to D
$this->write([
"@SP",
"D=M",
]);
// Write current stackpointer to LCL
$this->write([
"@LCL",
"M=D",
]);
// Reduce D height times = numArgs+5
$height = $numArgs + 5;
for ($i=0; $i < $height; $i++) {
$this->write([
"D=D-1",
]);
}
// now D = SP-n-5
// now we need to write D to ARG
$this->write([
"@ARG",
"M=D",
"@$functionName // Jump to $functionName",
"0;JMP",
"($label) // return back from function here",
]);
}
/**
* Writes the preable to initialize the VM
*/

View File

@ -72,6 +72,12 @@ class VMTranslator {
$this->writer->writeReturn();
break;
case CommandType::CALL:
$functionName = $parser->arg1();
$numberOfArgs = $parser->arg2();
$this->writer->writeCall($functionName, $numberOfArgs);
break;
default:
throw new \Exception("Not Implemented $command", 1);
break;