[07] StackTest passes
This commit is contained in:
parent
be69ac321d
commit
3fa5a5c07a
13
README.md
13
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)
|
## [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
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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 |
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue