[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)
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

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);
}
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() {