From cba1beefa4fba446ed1679356c2f5d9acdb8cb36 Mon Sep 17 00:00:00 2001 From: Nemo Date: Thu, 4 Jun 2020 15:43:38 +0530 Subject: [PATCH] [07/2] Finishes call/init implementation Found 2 bugs: 0. ic+=10 is incorrect jump for the boolean compare methods 1. Another bug was in the write() method, which was increasing the instruction counter even for label commands, which aren't supposed to do that. Another minor issue in my interpretation of the "call" to `Sys.init` which I was so far just doing via a jump. Changed that to a proper call --- .../FibonacciElement/FibonacciElement.asm | 787 ++++++++++-------- .../FibonacciElement/FibonacciElement.out | 2 +- vm/CodeWriter.php | 273 +++--- 3 files changed, 553 insertions(+), 509 deletions(-) diff --git a/projects/08/FunctionCalls/FibonacciElement/FibonacciElement.asm b/projects/08/FunctionCalls/FibonacciElement/FibonacciElement.asm index ada39c6..c923bd7 100644 --- a/projects/08/FunctionCalls/FibonacciElement/FibonacciElement.asm +++ b/projects/08/FunctionCalls/FibonacciElement/FibonacciElement.asm @@ -1,370 +1,417 @@ -@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 +@256 // init starts // (L0:0) +D=A // (L0:1) +@SP // (L0:2) +M=D // initialized SP to 256 // (L0:3) +@3000 // (L0:4) +D=A // (L0:5) +@LCL // (L0:6) +M=D // initialized @LCL to 3000 // (L0:7) +@4000 // (L0:8) +D=A // (L0:9) +@ARG // (L0:10) +M=D // initialized @ARG to 4000, init ends // (L0:11) +@18d95170022c2d762027b64da6c88d0a // call Sys.init 0 start // (L0:12) +D=A // (L0:13) +@SP // (L0:14) +A=M // (L0:15) +M=D // (L0:16) +@SP // (L0:17) +M=M+1 // (L0:18) +@LCL // Read @LCL to A // (L0:19) +D=M // Put @LCL to D // (L0:20) +@SP // (L0:21) +A=M // (L0:22) +M=D // Save @LCL to SP // (L0:23) +@SP // (L0:24) +M=M+1 // end @LCL pushed to SP // (L0:25) +@ARG // Read @ARG to A // (L0:26) +D=M // Put @ARG to D // (L0:27) +@SP // (L0:28) +A=M // (L0:29) +M=D // Save @ARG to SP // (L0:30) +@SP // (L0:31) +M=M+1 // end @ARG pushed to SP // (L0:32) +@THIS // Read @THIS to A // (L0:33) +D=M // Put @THIS to D // (L0:34) +@SP // (L0:35) +A=M // (L0:36) +M=D // Save @THIS to SP // (L0:37) +@SP // (L0:38) +M=M+1 // end @THIS pushed to SP // (L0:39) +@THAT // Read @THAT to A // (L0:40) +D=M // Put @THAT to D // (L0:41) +@SP // (L0:42) +A=M // (L0:43) +M=D // Save @THAT to SP // (L0:44) +@SP // (L0:45) +M=M+1 // end @THAT pushed to SP // (L0:46) +@SP // (L0:47) +D=M // (L0:48) +@LCL // (L0:49) +M=D // Update LCL=SP // (L0:50) +D=D-1 // should repeat 5 times // (L0:51) +D=D-1 // should repeat 5 times // (L0:52) +D=D-1 // should repeat 5 times // (L0:53) +D=D-1 // should repeat 5 times // (L0:54) +D=D-1 // should repeat 5 times // (L0:55) +@ARG // write D to ARG // (L0:56) +M=D // (L0:57) +@Sys.init // Jump to Sys.init // (L0:58) +0;JMP // (L0:59) +(18d95170022c2d762027b64da6c88d0a) // return back from function here (CALL ENDS) // (L0:60) +(Main.fibonacci) // function Main.fibonacci 0 // (L0:60) +@ARG // (L1:60) +A=M // (L1:61) +D=M // (L1:62) +@SP // (L1:63) +A=M // (L1:64) +M=D // (L1:65) +@SP // (L1:66) +M=M+1 // end push argument 0 // (L1:67) +@2 // push constant 2 // (L2:68) +D=A // (L2:69) +@SP // (L2:70) +A=M // (L2:71) +M=D // (L2:72) +@SP // (L2:73) +M=M+1 // end push constant 2 // (L2:74) +@SP // ==== lt ==== // (L3:75) +A=M-1 // (L3:76) +D=M // (L3:77) +A=A-1 // (L3:78) +D=M-D // (L3:79) +M=0 // (L3:80) +M=M-1 // (L3:81) +@89 // (L3:82) +D;JLT // (L3:83) +@SP // (L3:84) +A=M-1 // (L3:85) +A=A-1 // (L3:86) +M=0 // (L3:87) +@SP // (L3:88) +M=M-1 // end lt // (L3:89) +@SP // (L4:90) +AM=M-1 // (L4:91) +D=M // (L4:92) +@Main.fibonacciIF_TRUE // (L4:93) +D;JNE // end if-goto IF_TRUE // (L4:94) +@Main.fibonacciIF_FALSE // (L5:95) +0;JMP // end goto IF_FALSE // (L5:96) +(Main.fibonacciIF_TRUE) // end label IF_TRUE // (L6:97) +@ARG // (L7:97) +A=M // (L7:98) +D=M // (L7:99) +@SP // (L7:100) +A=M // (L7:101) +M=D // (L7:102) +@SP // (L7:103) +M=M+1 // end push argument 0 // (L7:104) +@SP // (L8:105) +A=M-1 // (L8:106) +D=M // (L8:107) +@ARG // (L8:108) +A=M // (L8:109) +M=D // (L8:110) +@ARG // (L8:111) +D=M+1 // (L8:112) +@SP // (L8:113) +M=D // @SP = ARG+1 // (L8:114) +@LCL // (L8:115) +D=M // (L8:116) +@R13 // (L8:117) +M=D // Save LCL to R13 // (L8:118) +A=D-1 // A=*LCL-1 // (L8:119) +D=M // D=*(*LCL-1) // (L8:120) +@THAT // A=THAT // (L8:121) +M=D // *that = *(*lcl-1) // (L8:122) +@R13 // (L8:123) +A=M-1 // (L8:124) +A=A-1 // A=*LCL-2 // (L8:125) +D=M // D=*(*LCL-2) // (L8:126) +@THIS // A=THIS // (L8:127) +M=D // *THIS = *(*lcl-2) // (L8:128) +@R13 // (L8:129) +A=M-1 // (L8:130) +A=A-1 // (L8:131) +A=A-1 // A=*LCL-3 // (L8:132) +D=M // D=*(*LCL-3) // (L8:133) +@ARG // A=ARG // (L8:134) +M=D // *ARG = *(*lcl-3) // (L8:135) +@R13 // (L8:136) +A=M-1 // (L8:137) +A=A-1 // (L8:138) +A=A-1 // (L8:139) +A=A-1 // A=*LCL-4 // (L8:140) +D=M // D=*(*LCL-4) // (L8:141) +@LCL // A=LCL // (L8:142) +M=D // *LCL = *(*lcl-4) // (L8:143) +@R13 // (L8:144) +A=M-1 // (L8:145) +A=A-1 // (L8:146) +A=A-1 // (L8:147) +A=A-1 // (L8:148) +A=A-1 // A=*LCL-5 // (L8:149) +A=M // A=*(*LCL-5) // (L8:150) +0;JMP // Jump to *(LCL-5) // (L8:151) +(Main.fibonacciIF_FALSE) // end label IF_FALSE // (L9:152) +@ARG // (L10:152) +A=M // (L10:153) +D=M // (L10:154) +@SP // (L10:155) +A=M // (L10:156) +M=D // (L10:157) +@SP // (L10:158) +M=M+1 // end push argument 0 // (L10:159) +@2 // push constant 2 // (L11:160) +D=A // (L11:161) +@SP // (L11:162) +A=M // (L11:163) +M=D // (L11:164) +@SP // (L11:165) +M=M+1 // end push constant 2 // (L11:166) +@SP // ==== sub ==== // (L12:167) +A=M-1 // (L12:168) +D=M // (L12:169) +A=A-1 // (L12:170) +M=M-D // (L12:171) +@SP // (L12:172) +M=M-1 // end sub // (L12:173) +@a3b7fa05917ee725f45e2c66ce232f37 // call Main.fibonacci 1 start // (L13:174) +D=A // (L13:175) +@SP // (L13:176) +A=M // (L13:177) +M=D // (L13:178) +@SP // (L13:179) +M=M+1 // (L13:180) +@LCL // Read @LCL to A // (L13:181) +D=M // Put @LCL to D // (L13:182) +@SP // (L13:183) +A=M // (L13:184) +M=D // Save @LCL to SP // (L13:185) +@SP // (L13:186) +M=M+1 // end @LCL pushed to SP // (L13:187) +@ARG // Read @ARG to A // (L13:188) +D=M // Put @ARG to D // (L13:189) +@SP // (L13:190) +A=M // (L13:191) +M=D // Save @ARG to SP // (L13:192) +@SP // (L13:193) +M=M+1 // end @ARG pushed to SP // (L13:194) +@THIS // Read @THIS to A // (L13:195) +D=M // Put @THIS to D // (L13:196) +@SP // (L13:197) +A=M // (L13:198) +M=D // Save @THIS to SP // (L13:199) +@SP // (L13:200) +M=M+1 // end @THIS pushed to SP // (L13:201) +@THAT // Read @THAT to A // (L13:202) +D=M // Put @THAT to D // (L13:203) +@SP // (L13:204) +A=M // (L13:205) +M=D // Save @THAT to SP // (L13:206) +@SP // (L13:207) +M=M+1 // end @THAT pushed to SP // (L13:208) +@SP // (L13:209) +D=M // (L13:210) +@LCL // (L13:211) +M=D // Update LCL=SP // (L13:212) +D=D-1 // should repeat 6 times // (L13:213) +D=D-1 // should repeat 6 times // (L13:214) +D=D-1 // should repeat 6 times // (L13:215) +D=D-1 // should repeat 6 times // (L13:216) +D=D-1 // should repeat 6 times // (L13:217) +D=D-1 // should repeat 6 times // (L13:218) +@ARG // write D to ARG // (L13:219) +M=D // (L13:220) +@Main.fibonacci // Jump to Main.fibonacci // (L13:221) +0;JMP // (L13:222) +(a3b7fa05917ee725f45e2c66ce232f37) // return back from function here (CALL ENDS) // (L13:223) +@ARG // (L14:223) +A=M // (L14:224) +D=M // (L14:225) +@SP // (L14:226) +A=M // (L14:227) +M=D // (L14:228) +@SP // (L14:229) +M=M+1 // end push argument 0 // (L14:230) +@1 // push constant 1 // (L15:231) +D=A // (L15:232) +@SP // (L15:233) +A=M // (L15:234) +M=D // (L15:235) +@SP // (L15:236) +M=M+1 // end push constant 1 // (L15:237) +@SP // ==== sub ==== // (L16:238) +A=M-1 // (L16:239) +D=M // (L16:240) +A=A-1 // (L16:241) +M=M-D // (L16:242) +@SP // (L16:243) +M=M-1 // end sub // (L16:244) +@59c3e1ed914ff5e6e713615a6bb2a5e2 // call Main.fibonacci 1 start // (L17:245) +D=A // (L17:246) +@SP // (L17:247) +A=M // (L17:248) +M=D // (L17:249) +@SP // (L17:250) +M=M+1 // (L17:251) +@LCL // Read @LCL to A // (L17:252) +D=M // Put @LCL to D // (L17:253) +@SP // (L17:254) +A=M // (L17:255) +M=D // Save @LCL to SP // (L17:256) +@SP // (L17:257) +M=M+1 // end @LCL pushed to SP // (L17:258) +@ARG // Read @ARG to A // (L17:259) +D=M // Put @ARG to D // (L17:260) +@SP // (L17:261) +A=M // (L17:262) +M=D // Save @ARG to SP // (L17:263) +@SP // (L17:264) +M=M+1 // end @ARG pushed to SP // (L17:265) +@THIS // Read @THIS to A // (L17:266) +D=M // Put @THIS to D // (L17:267) +@SP // (L17:268) +A=M // (L17:269) +M=D // Save @THIS to SP // (L17:270) +@SP // (L17:271) +M=M+1 // end @THIS pushed to SP // (L17:272) +@THAT // Read @THAT to A // (L17:273) +D=M // Put @THAT to D // (L17:274) +@SP // (L17:275) +A=M // (L17:276) +M=D // Save @THAT to SP // (L17:277) +@SP // (L17:278) +M=M+1 // end @THAT pushed to SP // (L17:279) +@SP // (L17:280) +D=M // (L17:281) +@LCL // (L17:282) +M=D // Update LCL=SP // (L17:283) +D=D-1 // should repeat 6 times // (L17:284) +D=D-1 // should repeat 6 times // (L17:285) +D=D-1 // should repeat 6 times // (L17:286) +D=D-1 // should repeat 6 times // (L17:287) +D=D-1 // should repeat 6 times // (L17:288) +D=D-1 // should repeat 6 times // (L17:289) +@ARG // write D to ARG // (L17:290) +M=D // (L17:291) +@Main.fibonacci // Jump to Main.fibonacci // (L17:292) +0;JMP // (L17:293) +(59c3e1ed914ff5e6e713615a6bb2a5e2) // return back from function here (CALL ENDS) // (L17:294) +@SP // ==== add ==== // (L18:294) +A=M-1 // (L18:295) +D=M // (L18:296) +A=A-1 // (L18:297) +M=D+M // (L18:298) +@SP // (L18:299) +M=M-1 // end add // (L18:300) +@SP // (L19:301) +A=M-1 // (L19:302) +D=M // (L19:303) +@ARG // (L19:304) +A=M // (L19:305) +M=D // (L19:306) +@ARG // (L19:307) +D=M+1 // (L19:308) +@SP // (L19:309) +M=D // @SP = ARG+1 // (L19:310) +@LCL // (L19:311) +D=M // (L19:312) +@R13 // (L19:313) +M=D // Save LCL to R13 // (L19:314) +A=D-1 // A=*LCL-1 // (L19:315) +D=M // D=*(*LCL-1) // (L19:316) +@THAT // A=THAT // (L19:317) +M=D // *that = *(*lcl-1) // (L19:318) +@R13 // (L19:319) +A=M-1 // (L19:320) +A=A-1 // A=*LCL-2 // (L19:321) +D=M // D=*(*LCL-2) // (L19:322) +@THIS // A=THIS // (L19:323) +M=D // *THIS = *(*lcl-2) // (L19:324) +@R13 // (L19:325) +A=M-1 // (L19:326) +A=A-1 // (L19:327) +A=A-1 // A=*LCL-3 // (L19:328) +D=M // D=*(*LCL-3) // (L19:329) +@ARG // A=ARG // (L19:330) +M=D // *ARG = *(*lcl-3) // (L19:331) +@R13 // (L19:332) +A=M-1 // (L19:333) +A=A-1 // (L19:334) +A=A-1 // (L19:335) +A=A-1 // A=*LCL-4 // (L19:336) +D=M // D=*(*LCL-4) // (L19:337) +@LCL // A=LCL // (L19:338) +M=D // *LCL = *(*lcl-4) // (L19:339) +@R13 // (L19:340) +A=M-1 // (L19:341) +A=A-1 // (L19:342) +A=A-1 // (L19:343) +A=A-1 // (L19:344) +A=A-1 // A=*LCL-5 // (L19:345) +A=M // A=*(*LCL-5) // (L19:346) +0;JMP // Jump to *(LCL-5) // (L19:347) +(Sys.init) // function Sys.init 0 // (L20:348) +@4 // push constant 4 // (L21:348) +D=A // (L21:349) +@SP // (L21:350) +A=M // (L21:351) +M=D // (L21:352) +@SP // (L21:353) +M=M+1 // end push constant 4 // (L21:354) +@c28123f096da12e9e9a4357d4823b8d2 // call Main.fibonacci 1 start // (L22:355) +D=A // (L22:356) +@SP // (L22:357) +A=M // (L22:358) +M=D // (L22:359) +@SP // (L22:360) +M=M+1 // (L22:361) +@LCL // Read @LCL to A // (L22:362) +D=M // Put @LCL to D // (L22:363) +@SP // (L22:364) +A=M // (L22:365) +M=D // Save @LCL to SP // (L22:366) +@SP // (L22:367) +M=M+1 // end @LCL pushed to SP // (L22:368) +@ARG // Read @ARG to A // (L22:369) +D=M // Put @ARG to D // (L22:370) +@SP // (L22:371) +A=M // (L22:372) +M=D // Save @ARG to SP // (L22:373) +@SP // (L22:374) +M=M+1 // end @ARG pushed to SP // (L22:375) +@THIS // Read @THIS to A // (L22:376) +D=M // Put @THIS to D // (L22:377) +@SP // (L22:378) +A=M // (L22:379) +M=D // Save @THIS to SP // (L22:380) +@SP // (L22:381) +M=M+1 // end @THIS pushed to SP // (L22:382) +@THAT // Read @THAT to A // (L22:383) +D=M // Put @THAT to D // (L22:384) +@SP // (L22:385) +A=M // (L22:386) +M=D // Save @THAT to SP // (L22:387) +@SP // (L22:388) +M=M+1 // end @THAT pushed to SP // (L22:389) +@SP // (L22:390) +D=M // (L22:391) +@LCL // (L22:392) +M=D // Update LCL=SP // (L22:393) +D=D-1 // should repeat 6 times // (L22:394) +D=D-1 // should repeat 6 times // (L22:395) +D=D-1 // should repeat 6 times // (L22:396) +D=D-1 // should repeat 6 times // (L22:397) +D=D-1 // should repeat 6 times // (L22:398) +D=D-1 // should repeat 6 times // (L22:399) +@ARG // write D to ARG // (L22:400) +M=D // (L22:401) +@Main.fibonacci // Jump to Main.fibonacci // (L22:402) +0;JMP // (L22:403) +(c28123f096da12e9e9a4357d4823b8d2) // return back from function here (CALL ENDS) // (L22:404) +(Sys.initWHILE) // end label WHILE // (L23:404) +@Sys.initWHILE // (L24:404) +0;JMP // end goto WHILE // (L24:405) +@407 // (L25:406) +0;JMP // (L25:407) diff --git a/projects/08/FunctionCalls/FibonacciElement/FibonacciElement.out b/projects/08/FunctionCalls/FibonacciElement/FibonacciElement.out index 546d784..fdf5e2d 100644 --- a/projects/08/FunctionCalls/FibonacciElement/FibonacciElement.out +++ b/projects/08/FunctionCalls/FibonacciElement/FibonacciElement.out @@ -1,2 +1,2 @@ | RAM[0] |RAM[261]| -| 257 | 0 | +| 262 | 3 | diff --git a/vm/CodeWriter.php b/vm/CodeWriter.php index 4afdf10..c97b427 100644 --- a/vm/CodeWriter.php +++ b/vm/CodeWriter.php @@ -17,65 +17,65 @@ function __construct($outputFile) { public function writeReturn() { $this->write([ - "@SP", - "A=M-1", - "D=M",// Popped value to D + '@SP', + 'A=M-1', + 'D=M',// Popped value to D // And then write it to *ARG = pop() - "@ARG", - "A=M", - "M=D", + '@ARG', + 'A=M', + 'M=D', // SP=ARG+1 - "@ARG", - "D=M+1", - "@SP", - "M=D // @SP = ARG+1", - "@LCL", - "D=M", - "@R13", - "M=D // Save LCL to R13", + '@ARG', + 'D=M+1', + '@SP', + 'M=D // @SP = ARG+1', + '@LCL', + 'D=M', + '@R13', + 'M=D // Save LCL to R13', // now we go restoring THAT, THIS, ARG, LCL - "A=D-1 // A=*LCL-1", - "D=M // D=*(*LCL-1)", - "@THAT // A=THAT", - "M=D // *that = *(*lcl-1)", + 'A=D-1 // A=*LCL-1', + 'D=M // D=*(*LCL-1)', + '@THAT // A=THAT', + 'M=D // *that = *(*lcl-1)', // now we restore THIS - "@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=*LCL-2', + 'D=M // D=*(*LCL-2)', + '@THIS // A=THIS', + 'M=D // *THIS = *(*lcl-2)', // now we restore ARG - "@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=*LCL-3', + 'D=M // D=*(*LCL-3)', + '@ARG // A=ARG', + 'M=D // *ARG = *(*lcl-3)', // now we restore LCL - "@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=*LCL-4', + 'D=M // D=*(*LCL-4)', + '@LCL // A=LCL', + 'M=D // *LCL = *(*lcl-4)', // Now we hyperjump - "@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)", + '@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)', ]); } @@ -97,7 +97,8 @@ public function writeFunction($name, $numArgs) { if ($numArgs > 0) { $this->write([ // This is only required for the first argument - "@SP", "A=M" + '@SP', + 'A=M', ]); } @@ -105,9 +106,9 @@ public function writeFunction($name, $numArgs) { // push a zero to the stack for($i=0;$i<$numArgs;$i++) { $this->write([ - "M=0", - "@SP", - "AM=M+1", + 'M=0', + '@SP', + 'AM=M+1', ]); } } @@ -121,20 +122,20 @@ public function writeCall(String $functionName, $numArgs) { // push the label to top of the stack $this->write([ - "@$label", - "D=A", - "@SP", - "A=M", - "M=D", - "@SP", - "M=M+1" + "@$label // call $functionName $numArgs start", + 'D=A', + '@SP', + 'A=M', + 'M=D', + '@SP', + 'M=M+1', ]); $pushes = [ - "@LCL", - "@ARG", - "@THIS", - "@THAT", + '@LCL', + '@ARG', + '@THIS', + '@THAT', ]; // TODO: optimize this by saving LCL, ARG @@ -144,42 +145,39 @@ public function writeCall(String $functionName, $numArgs) { $this->write([ "$lookupRegister // Read $lookupRegister to A", "D=M // Put $lookupRegister to D", - "@SP", - "A=M", + '@SP', + 'A=M', "M=D // Save $lookupRegister to SP", - "@SP", - "M=M+1", + '@SP', + "M=M+1 // end $lookupRegister pushed to SP", ]); } // Load current stackpointer to D + // and write it to LCL $this->write([ - "@SP", - "D=M", - ]); - - // Write current stackpointer to LCL - $this->write([ - "@LCL", - "M=D", + '@SP', + 'D=M', + '@LCL', + 'M=D // Update LCL=SP', ]); // Reduce D height times = numArgs+5 $height = $numArgs + 5; for ($i=0; $i < $height; $i++) { $this->write([ - "D=D-1", + "D=D-1 // should repeat $height times", ]); } // now D = SP-n-5 // now we need to write D to ARG $this->write([ - "@ARG", - "M=D", + '@ARG // write D to ARG', + 'M=D', "@$functionName // Jump to $functionName", - "0;JMP", - "($label) // return back from function here", + '0;JMP', + "($label) // return back from function here (CALL ENDS)", ]); } @@ -188,22 +186,21 @@ public function writeCall(String $functionName, $numArgs) { */ private function writeInit() { $this->write([ - "@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", - // We jump to Sys.init - "@Sys.init", - "0;JMP" + '@256 // init starts', + 'D=A', + '@SP', + 'M=D // initialized SP to 256', + '@3000', + 'D=A', + '@LCL', + 'M=D // initialized @LCL to 3000', + '@4000', + 'D=A', + '@ARG', + 'M=D // initialized @ARG to 4000, init ends', ]); + + $this->writeCall('Sys.init', 0); } function setInputFileName($inputFileName) { @@ -226,7 +223,7 @@ function close() { $endJump = $this->ic+1; $this->write([ "@$endJump", - "0;JMP" + '0;JMP', ]); } @@ -236,7 +233,7 @@ function close() { function writeLabel(String $label) { $globalLabel = $this->resolveLabel($label); $this->write([ - "($globalLabel) // end label $label (L{$this->sourceLine})", + "($globalLabel) // end label $label", ]); } @@ -257,7 +254,7 @@ public function writeGoto(String $label) { $globalLabel = $this->resolveLabel($label); $this->write([ "@$globalLabel", - "0;JMP // end goto $label (L{$this->sourceLine})", + "0;JMP // end goto $label", ]); } @@ -274,7 +271,7 @@ function writeIf(String $label) { 'AM=M-1', 'D=M', "@$globalLabel", - "D;JNE // end if-goto $label (L{$this->sourceLine})", + "D;JNE // end if-goto $label", ]); } @@ -283,8 +280,8 @@ function writeArithmetic(String $command) { // Read top of stack to D $this->write([ "@SP // ==== $command ====", - "A=M-1", - "D=M" + 'A=M-1', + 'D=M' ]); switch ($command) { @@ -293,7 +290,7 @@ function writeArithmetic(String $command) { case 'sub': $this->write([ 'A=A-1', - "M=M-D", + 'M=M-D', ]); break; @@ -307,7 +304,7 @@ function writeArithmetic(String $command) { case 'neg': $this->write([ - "M=-M // end $command (L{$this->sourceLine})", + "M=-M // end $command", ]); $stackDecrease = false; break; @@ -315,7 +312,7 @@ function writeArithmetic(String $command) { case 'not': $this->write([ - "M=!M // end $command (L{$this->sourceLine})", + "M=!M // end $command", ]); $stackDecrease = false; break; @@ -336,23 +333,23 @@ function writeArithmetic(String $command) { // TODO: Combine all the boolean commands case 'lt': - $jumpPointer = $this->ic+10; + $jumpPointer = $this->ic+11; $this->write([ 'A=A-1', 'D=M-D', 'M=0', 'M=M-1', "@$jumpPointer", - "D;JLT", - "@SP", - "A=M-1", - "A=A-1", - "M=0", + 'D;JLT', + '@SP', + 'A=M-1', + 'A=A-1', + 'M=0', ]); break; case 'gt': - $jumpPointer = $this->ic+10; + $jumpPointer = $this->ic+11; $this->write([ 'A=A-1', 'D=M-D', @@ -360,15 +357,15 @@ function writeArithmetic(String $command) { 'M=M-1', "@$jumpPointer", "D;JGT", - "@SP", - "A=M-1", - "A=A-1", - "M=0", + '@SP', + 'A=M-1', + 'A=A-1', + 'M=0', ]); break; case 'eq': - $jumpPointer = $this->ic+10; + $jumpPointer = $this->ic+11; $this->write([ 'A=A-1', 'D=M-D', @@ -376,10 +373,10 @@ function writeArithmetic(String $command) { 'M=M-1', "@{$jumpPointer}", 'D;JEQ', - "@SP", - "A=M-1", - "A=A-1", - "M=0", + '@SP', + 'A=M-1', + 'A=A-1', + 'M=0', ]); break; @@ -391,17 +388,17 @@ function writeArithmetic(String $command) { if ($stackDecrease) { $this->write([ '@SP', - "M=M-1 // end $command (L{$this->sourceLine})" + "M=M-1 // end $command" ]); } } private function write(Array $lines) { foreach ($lines as $line) { - if (substr($line, 0, 2) !== "//") { + fwrite($this->file, "$line // (L{$this->sourceLine}:{$this->ic})\n"); + if (substr($line, 0, 2) !== "//" and substr($line, 0, 1) !== "(") { $this->ic += 1; } - fwrite($this->file, "$line\n"); } } @@ -419,7 +416,7 @@ function writePush(String $segment, Int $index) { // Take the constant "@$index // push $segment $index", // Write it to D - "D=A", + 'D=A', ]); break; case 'argument': @@ -433,8 +430,8 @@ function writePush(String $segment, Int $index) { } $this->write([ $register, - "A=M", - "D=M", + 'A=M', + 'D=M', ]); break; @@ -442,7 +439,7 @@ function writePush(String $segment, Int $index) { $symbol = $this->resolveStatic($index); $this->write([ $symbol, - "D=M" + 'D=M' ]); break; @@ -450,7 +447,7 @@ function writePush(String $segment, Int $index) { $register = $this->resolvePointer($index); $this->write([ "$register // pointer $index", - "D=M" + 'D=M' ]); break; @@ -458,7 +455,7 @@ function writePush(String $segment, Int $index) { $register = $this->resolveTemp($index); $this->write([ "$register // temp $index", - "D=M" + 'D=M' ]); break; @@ -475,7 +472,7 @@ function writePush(String $segment, Int $index) { "M=D", // Bump Stack Pointer "@SP", - "M=M+1 // end push $segment $index (L{$this->sourceLine})", + "M=M+1 // end push $segment $index", ]); } @@ -500,7 +497,7 @@ private function resolveSegmentToR13(string $segment, Int $index) { $register = $this->resolveSegmentToRegister($segment); $this->write([ "$register // $segment $index" , - "D=M", + 'D=M', "@$index // write $index to A", "D=D+A // D = segment+index", "@R13 // save it to R13", @@ -533,10 +530,10 @@ private function writePop(String $segment, Int $index) { $this->write([ "@SP // pop", "AM=M-1", - "D=M", + 'D=M', $lookupRegister, "A=M // Read $lookupRegister to A (for $segment $index)", - "M=D // end pop $segment $index (L{$this->sourceLine})", + "M=D // end pop $segment $index", ]); break; @@ -545,9 +542,9 @@ private function writePop(String $segment, Int $index) { $this->write([ "@SP //pop $segment $index", "AM=M-1", - "D=M", + 'D=M', $symbol, - "M=D // end pop $segment $index (L{$this->sourceLine})" + "M=D // end pop $segment $index" ]); break; @@ -557,9 +554,9 @@ private function writePop(String $segment, Int $index) { $this->write([ "@SP // pop", "AM=M-1", - "D=M", + 'D=M', $register, - "M=D // (L{$this->sourceLine})" + "M=D //" ]); break; @@ -568,9 +565,9 @@ private function writePop(String $segment, Int $index) { $this->write([ "@SP", "AM=M-1", - "D=M", + 'D=M', "$tempRegister", - "M=D // end pop temp $index (L{$this->sourceLine})" + "M=D // end pop temp $index" ]); break;