From 3fa5a5c07afa4c4bdab3bab274a5ce15dfced3de Mon Sep 17 00:00:00 2001 From: Nemo Date: Tue, 2 Jun 2020 00:10:15 +0530 Subject: [PATCH] [07] StackTest passes --- README.md | 13 +- .../StackArithmetic/StackTest/StackTest.asm | 334 ++++++++++++++++++ .../StackArithmetic/StackTest/StackTest.out | 4 + vm/VMTranslator.php | 132 +++++-- 4 files changed, 454 insertions(+), 29 deletions(-) create mode 100644 projects/07/StackArithmetic/StackTest/StackTest.asm create mode 100644 projects/07/StackArithmetic/StackTest/StackTest.out diff --git a/README.md b/README.md index 8d689fb..a78cbd8 100644 --- a/README.md +++ b/README.md @@ -92,10 +92,19 @@ Counting number of instructions by `wc -l $file.hack` ## [Project 6: Virtual Machine I - Stack Arithmetic](https://www.nand2tetris.org/project07) +Final hack instruction set count in brackets. Calculated by running: + + +``` +php file.vm > file.asm +ruby assembler.rb file.vm > file.hack +wc -l file.hack +``` + ### Arithmetic Commands -- [ ] SimpleAdd.vm -- [ ] StackTest.vm +- [x] SimpleAdd.vm (21) +- [x] StackTest.vm (334) ### Memory Access Commands diff --git a/projects/07/StackArithmetic/StackTest/StackTest.asm b/projects/07/StackArithmetic/StackTest/StackTest.asm new file mode 100644 index 0000000..7c4a6ac --- /dev/null +++ b/projects/07/StackArithmetic/StackTest/StackTest.asm @@ -0,0 +1,334 @@ +@17 // push constant 17 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 17 +@17 // push constant 17 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 17 +@SP // ==== eq ==== +A=M-1 +D=M +A=A-1 +D=M-D +M=0 +M=M-1 +@27 +D;JEQ +@SP +A=M-1 +A=A-1 +M=0 +@SP +M=M-1 +@17 // push constant 17 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 17 +@16 // push constant 16 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 16 +@SP // ==== eq ==== +A=M-1 +D=M +A=A-1 +D=M-D +M=0 +M=M-1 +@56 +D;JEQ +@SP +A=M-1 +A=A-1 +M=0 +@SP +M=M-1 +@16 // push constant 16 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 16 +@17 // push constant 17 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 17 +@SP // ==== eq ==== +A=M-1 +D=M +A=A-1 +D=M-D +M=0 +M=M-1 +@85 +D;JEQ +@SP +A=M-1 +A=A-1 +M=0 +@SP +M=M-1 +@892 // push constant 892 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 892 +@891 // push constant 891 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 891 +@SP // ==== lt ==== +A=M-1 +D=M +A=A-1 +D=M-D +M=0 +M=M-1 +@114 +D;JLT +@SP +A=M-1 +A=A-1 +M=0 +@SP +M=M-1 +@891 // push constant 891 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 891 +@892 // push constant 892 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 892 +@SP // ==== lt ==== +A=M-1 +D=M +A=A-1 +D=M-D +M=0 +M=M-1 +@143 +D;JLT +@SP +A=M-1 +A=A-1 +M=0 +@SP +M=M-1 +@891 // push constant 891 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 891 +@891 // push constant 891 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 891 +@SP // ==== lt ==== +A=M-1 +D=M +A=A-1 +D=M-D +M=0 +M=M-1 +@172 +D;JLT +@SP +A=M-1 +A=A-1 +M=0 +@SP +M=M-1 +@32767 // push constant 32767 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 32767 +@32766 // push constant 32766 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 32766 +@SP // ==== gt ==== +A=M-1 +D=M +A=A-1 +D=M-D +M=0 +M=M-1 +@201 +D;JGT +@SP +A=M-1 +A=A-1 +M=0 +@SP +M=M-1 +@32766 // push constant 32766 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 32766 +@32767 // push constant 32767 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 32767 +@SP // ==== gt ==== +A=M-1 +D=M +A=A-1 +D=M-D +M=0 +M=M-1 +@230 +D;JGT +@SP +A=M-1 +A=A-1 +M=0 +@SP +M=M-1 +@32766 // push constant 32766 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 32766 +@32766 // push constant 32766 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 32766 +@SP // ==== gt ==== +A=M-1 +D=M +A=A-1 +D=M-D +M=0 +M=M-1 +@259 +D;JGT +@SP +A=M-1 +A=A-1 +M=0 +@SP +M=M-1 +@57 // push constant 57 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 57 +@31 // push constant 31 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 31 +@53 // push constant 53 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 53 +@SP // ==== add ==== +A=M-1 +D=M +A=A-1 +M=D+M +@SP +M=M-1 +@112 // push constant 112 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 112 +@SP // ==== sub ==== +A=M-1 +D=M +A=A-1 +M=M-D +@SP +M=M-1 +@SP // ==== neg ==== +A=M-1 +D=M +M=-M +@SP // ==== and ==== +A=M-1 +D=M +A=A-1 +M=D&M +@SP +M=M-1 +@82 // push constant 82 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 82 +@SP // ==== or ==== +A=M-1 +D=M +A=A-1 +M=D|M +@SP +M=M-1 +@SP // ==== not ==== +A=M-1 +D=M +M=!M +@333 +0;JMP diff --git a/projects/07/StackArithmetic/StackTest/StackTest.out b/projects/07/StackArithmetic/StackTest/StackTest.out new file mode 100644 index 0000000..cb182ec --- /dev/null +++ b/projects/07/StackArithmetic/StackTest/StackTest.out @@ -0,0 +1,4 @@ +| RAM[0] | RAM[256] | RAM[257] | RAM[258] | RAM[259] | RAM[260] | +| 266 | -1 | 0 | 0 | 0 | -1 | +| RAM[261] | RAM[262] | RAM[263] | RAM[264] | RAM[265] | +| 0 | -1 | 0 | 0 | -91 | diff --git a/vm/VMTranslator.php b/vm/VMTranslator.php index 8781a4a..c5cbcd1 100644 --- a/vm/VMTranslator.php +++ b/vm/VMTranslator.php @@ -76,48 +76,127 @@ class CodeWriter { fclose($this->file); } + function close() { + $endJump = $this->ic+1; + $this->write([ + "@$endJump", + "0;JMP" + ]); + } + function writeArithmetic(String $command ) { + $stackDecrease=true; // Read top of stack to D $this->write([ - "// ==== $command ====", - "// pop starts", - "@SP", + "@SP // ==== $command ====", "A=M-1", - "D=M", - "// pop ends", - "// inner $command starts", - 'A=A-1', + "D=M" ]); + switch ($command) { + case 'sub': + $this->write([ + 'A=A-1', + "M=M-D", + ]); + break; + case 'add': // But add it to previous D this time $this->write([ - "M=D+M" + 'A=A-1', + 'M=D+M' + ]); + break; + + case 'neg': + $this->write([ + 'M=-M', + ]); + $stackDecrease = false; + break; + + + case 'not': + $this->write([ + 'M=!M', + ]); + $stackDecrease = false; + break; + + case 'and': + $this->write([ + 'A=A-1', + 'M=D&M', + ]); + break; + + case 'or': + $this->write([ + 'A=A-1', + 'M=D|M', + ]); + break; + + case 'lt': + $jumpPointer = $this->ic+10; + $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", + ]); + break; + + case 'gt': + $jumpPointer = $this->ic+10; + $this->write([ + 'A=A-1', + 'D=M-D', + 'M=0', + 'M=M-1', + "@$jumpPointer", + "D;JGT", + "@SP", + "A=M-1", + "A=A-1", + "M=0", ]); break; case 'eq': - $jumpPointer = $this->ic+5; + $jumpPointer = $this->ic+10; $this->write([ - 'D=M-D', // ic - 'M=0', // set M=0, in case they aren't equal - "@{jumpPointer}", - 'D;JEQ', //ic+2 - 'M=0', //ic+3 - 'M=M-1', //ic+4 - // set M=-1 (TRUE), in case they are equal - // *SP=-1 = true + 'A=A-1', + 'D=M-D', + 'M=0', + 'M=M-1', + "@{$jumpPointer}", + 'D;JEQ', + "@SP", + "A=M-1", + "A=A-1", + "M=0", ]); + break; default: - # code... - break; + throw new \Exception("$command not Implemented", 1); + } - $this->write([ - '@SP', - 'M=M-1' - ]); + if ($stackDecrease) { + $this->write([ + '@SP', + 'M=M-1' + ]); + } } private function write(Array $lines) { @@ -133,9 +212,8 @@ class CodeWriter { switch ($segment) { case 'constant': $this->write([ - "// push $segment $index", // Take the constant - "@$index", + "@$index // push $segment $index", // Write it to D "D=A", // A=SP @@ -145,8 +223,7 @@ class CodeWriter { "M=D", // Bump Stack Pointer "@SP", - "M=M+1", - "// end push $segment $index" + "M=M+1 // end push $segment $index", ]); break; @@ -213,6 +290,7 @@ class VMTranslator { } } } + $this->writer->close(); } private function outputFile() {