[07] StackTest passes

This commit is contained in:
Nemo 2020-06-02 00:10:15 +05:30
parent be69ac321d
commit 3fa5a5c07a
4 changed files with 454 additions and 29 deletions

View File

@ -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) ## [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 ### Arithmetic Commands
- [ ] SimpleAdd.vm - [x] SimpleAdd.vm (21)
- [ ] StackTest.vm - [x] StackTest.vm (334)
### Memory Access Commands ### Memory Access Commands

View File

@ -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

View File

@ -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 |

View File

@ -76,48 +76,127 @@ class CodeWriter {
fclose($this->file); fclose($this->file);
} }
function close() {
$endJump = $this->ic+1;
$this->write([
"@$endJump",
"0;JMP"
]);
}
function writeArithmetic(String $command ) { function writeArithmetic(String $command ) {
$stackDecrease=true;
// Read top of stack to D // Read top of stack to D
$this->write([ $this->write([
"// ==== $command ====", "@SP // ==== $command ====",
"// pop starts",
"@SP",
"A=M-1", "A=M-1",
"D=M", "D=M"
"// pop ends",
"// inner $command starts",
'A=A-1',
]); ]);
switch ($command) { switch ($command) {
case 'sub':
$this->write([
'A=A-1',
"M=M-D",
]);
break;
case 'add': case 'add':
// But add it to previous D this time // But add it to previous D this time
$this->write([ $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; break;
case 'eq': case 'eq':
$jumpPointer = $this->ic+5; $jumpPointer = $this->ic+10;
$this->write([ $this->write([
'D=M-D', // ic 'A=A-1',
'M=0', // set M=0, in case they aren't equal 'D=M-D',
"@{jumpPointer}", 'M=0',
'D;JEQ', //ic+2 'M=M-1',
'M=0', //ic+3 "@{$jumpPointer}",
'M=M-1', //ic+4 'D;JEQ',
// set M=-1 (TRUE), in case they are equal "@SP",
// *SP=-1 = true "A=M-1",
"A=A-1",
"M=0",
]); ]);
break;
default: default:
# code... throw new \Exception("$command not Implemented", 1);
break;
} }
$this->write([ if ($stackDecrease) {
'@SP', $this->write([
'M=M-1' '@SP',
]); 'M=M-1'
]);
}
} }
private function write(Array $lines) { private function write(Array $lines) {
@ -133,9 +212,8 @@ class CodeWriter {
switch ($segment) { switch ($segment) {
case 'constant': case 'constant':
$this->write([ $this->write([
"// push $segment $index",
// Take the constant // Take the constant
"@$index", "@$index // push $segment $index",
// Write it to D // Write it to D
"D=A", "D=A",
// A=SP // A=SP
@ -145,8 +223,7 @@ class CodeWriter {
"M=D", "M=D",
// Bump Stack Pointer // Bump Stack Pointer
"@SP", "@SP",
"M=M+1", "M=M+1 // end push $segment $index",
"// end push $segment $index"
]); ]);
break; break;
@ -213,6 +290,7 @@ class VMTranslator {
} }
} }
} }
$this->writer->close();
} }
private function outputFile() { private function outputFile() {