.
This commit is contained in:
Executable
+29
@@ -0,0 +1,29 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Array.jack
|
||||
|
||||
/**
|
||||
* Represents an array.
|
||||
* In the Jack language, arrays are instances of the Array class.
|
||||
* Once declared, the array entries can be accessed using the usual
|
||||
* syntax arr[i]. Each array entry can hold a primitive data type as
|
||||
* well as any object type. Different array entries can have different
|
||||
* data types.
|
||||
*/
|
||||
class Array {
|
||||
|
||||
/** Constructs a new Array of the given size. */
|
||||
function Array new(int size) {
|
||||
if(size < 0){
|
||||
do Sys.error(7);
|
||||
}
|
||||
return Memory.alloc(size);
|
||||
}
|
||||
|
||||
/** Disposes this array. */
|
||||
method void dispose() {
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Array.jack
|
||||
|
||||
/**
|
||||
* Represents an array.
|
||||
* In the Jack language, arrays are instances of the Array class.
|
||||
* Once declared, the array entries can be accessed using the usual
|
||||
* syntax arr[i]. Each array entry can hold a primitive data type as
|
||||
* well as any object type. Different array entries can have different
|
||||
* data types.
|
||||
*/
|
||||
class Array {
|
||||
|
||||
/** Constructs a new Array of the given size. */
|
||||
function Array new(int size) {
|
||||
if(size < 0){
|
||||
do Sys.error(7);
|
||||
}
|
||||
return Memory.alloc(size);
|
||||
}
|
||||
|
||||
/** Disposes this array. */
|
||||
method void dispose() {
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
function Array.new 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L0
|
||||
push constant 7
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L1
|
||||
label L0
|
||||
label L1
|
||||
push argument 0
|
||||
call Memory.alloc 1
|
||||
return
|
||||
function Array.dispose 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push pointer 0
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|
|
||||
| 222 | 122 | 100 | 10 |
|
||||
Executable
Executable
+15
@@ -0,0 +1,15 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/ArrayTest/ArrayTest.tst
|
||||
|
||||
load,
|
||||
output-file ArrayTest.out,
|
||||
compare-to ArrayTest.cmp,
|
||||
output-list RAM[8000]%D2.6.1 RAM[8001]%D2.6.1 RAM[8002]%D2.6.1 RAM[8003]%D2.6.1;
|
||||
|
||||
repeat 1000000 {
|
||||
vmstep;
|
||||
}
|
||||
|
||||
output;
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/ArrayTest/Main.jack
|
||||
|
||||
/** Test program for the OS Array class. */
|
||||
class Main {
|
||||
|
||||
/** Performs several Array manipulations. */
|
||||
function void main() {
|
||||
var Array r; // stores test results
|
||||
var Array a, b, c;
|
||||
|
||||
let r = 8000;
|
||||
|
||||
let a = Array.new(3);
|
||||
let a[2] = 222;
|
||||
let r[0] = a[2]; // RAM[8000] = 222
|
||||
|
||||
let b = Array.new(3);
|
||||
let b[1] = a[2] - 100;
|
||||
let r[1] = b[1]; // RAM[8001] = 122
|
||||
|
||||
let c = Array.new(500);
|
||||
let c[499] = a[2] - b[1];
|
||||
let r[2] = c[499]; // RAM[8002] = 100
|
||||
|
||||
do a.dispose();
|
||||
do b.dispose();
|
||||
|
||||
let b = Array.new(3);
|
||||
let b[0] = c[499] - 90;
|
||||
let r[3] = b[0]; // RAM[8003] = 10
|
||||
|
||||
do c.dispose();
|
||||
do b.dispose();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+131
@@ -0,0 +1,131 @@
|
||||
function Main.main 4
|
||||
push constant 8000
|
||||
pop local 0
|
||||
push constant 3
|
||||
call Array.new 1
|
||||
pop local 1
|
||||
push local 1
|
||||
push constant 2
|
||||
push constant 222
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 0
|
||||
push local 1
|
||||
push constant 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 3
|
||||
call Array.new 1
|
||||
pop local 2
|
||||
push local 2
|
||||
push constant 1
|
||||
push local 1
|
||||
push constant 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 100
|
||||
sub
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
push local 2
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 500
|
||||
call Array.new 1
|
||||
pop local 3
|
||||
push local 3
|
||||
push constant 499
|
||||
push local 1
|
||||
push constant 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 2
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
sub
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 2
|
||||
push local 3
|
||||
push constant 499
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 1
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
push local 2
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
push constant 3
|
||||
call Array.new 1
|
||||
pop local 2
|
||||
push local 2
|
||||
push constant 0
|
||||
push local 3
|
||||
push constant 499
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 90
|
||||
sub
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 3
|
||||
push local 2
|
||||
push constant 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 3
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
push local 2
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+102
@@ -0,0 +1,102 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Keyboard.jack
|
||||
|
||||
/**
|
||||
* A library for handling user input from the keyboard.
|
||||
*/
|
||||
|
||||
class Keyboard {
|
||||
static Array mem;
|
||||
/** Initializes the keyboard. */
|
||||
function void init() {
|
||||
let mem = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the character of the currently pressed key on the keyboard;
|
||||
* if no key is currently pressed, returns 0.
|
||||
*
|
||||
* Recognizes all ASCII characters, as well as the following keys:
|
||||
* new line = 128 = String.newline()
|
||||
* backspace = 129 = String.backspace()
|
||||
* left arrow = 130
|
||||
* up arrow = 131
|
||||
* right arrow = 132
|
||||
* down arrow = 133
|
||||
* home = 134
|
||||
* End = 135
|
||||
* page up = 136
|
||||
* page down = 137
|
||||
* insert = 138
|
||||
* delete = 139
|
||||
* ESC = 140
|
||||
* F1 - F12 = 141 - 152
|
||||
*/
|
||||
function char keyPressed() {
|
||||
return mem[24576];
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until a key is pressed on the keyboard and released,
|
||||
* then echoes the key to the screen, and returns the character
|
||||
* of the pressed key.
|
||||
*/
|
||||
function char readChar() {
|
||||
var char a, b;
|
||||
do Output.printChar(0);
|
||||
while ((b = 0) | (a > 0)){
|
||||
let a = Keyboard.keyPressed();
|
||||
if (a > 0){
|
||||
let b = a;
|
||||
}
|
||||
}
|
||||
do Output.printChar(String.backSpace());
|
||||
do Output.printChar(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the message on the screen, reads from the keyboard the entered
|
||||
* text until a newline character is detected, echoes the text to the screen,
|
||||
* and returns its value. Also handles user backspaces.
|
||||
*/
|
||||
function String readLine(String message) {
|
||||
var String s, b;
|
||||
var char c;
|
||||
let s = String.new(100);
|
||||
do Output.printString(message);
|
||||
while (true){
|
||||
let c = Keyboard.readChar();
|
||||
if (c = 128){
|
||||
return s;
|
||||
}
|
||||
else{
|
||||
if (c = 129){
|
||||
do s.eraseLastChar();
|
||||
}
|
||||
else{
|
||||
do s.appendChar(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the message on the screen, reads from the keyboard the entered
|
||||
* text until a newline character is detected, echoes the text to the screen,
|
||||
* and returns its integer value (until the first non-digit character in the
|
||||
* entered text is detected). Also handles user backspaces.
|
||||
*/
|
||||
function int readInt(String message) {
|
||||
var starting a;
|
||||
var int b;
|
||||
let a = Main.readLine_stolen(message);
|
||||
let b = String.intValue(a);
|
||||
do String.dispose(a);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
Executable
+101
@@ -0,0 +1,101 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Keyboard.jack
|
||||
|
||||
/**
|
||||
* A library for handling user input from the keyboard.
|
||||
*/
|
||||
|
||||
class Keyboard {
|
||||
static Array mem;
|
||||
/** Initializes the keyboard. */
|
||||
function void init() {
|
||||
let mem = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the character of the currently pressed key on the keyboard;
|
||||
* if no key is currently pressed, returns 0.
|
||||
*
|
||||
* Recognizes all ASCII characters, as well as the following keys:
|
||||
* new line = 128 = String.newline()
|
||||
* backspace = 129 = String.backspace()
|
||||
* left arrow = 130
|
||||
* up arrow = 131
|
||||
* right arrow = 132
|
||||
* down arrow = 133
|
||||
* home = 134
|
||||
* End = 135
|
||||
* page up = 136
|
||||
* page down = 137
|
||||
* insert = 138
|
||||
* delete = 139
|
||||
* ESC = 140
|
||||
* F1 - F12 = 141 - 152
|
||||
*/
|
||||
function char keyPressed() {
|
||||
return mem[24576];
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until a key is pressed on the keyboard and released,
|
||||
* then echoes the key to the screen, and returns the character
|
||||
* of the pressed key.
|
||||
*/
|
||||
function char readChar() {
|
||||
var char a, b;
|
||||
do Output.printChar(0);
|
||||
while ((b = 0) | (a > 0)){
|
||||
let a = Keyboard.keyPressed();
|
||||
if (a > 0){
|
||||
let b = a;
|
||||
}
|
||||
}
|
||||
do Output.printChar(String.backSpace());
|
||||
do Output.printChar(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the message on the screen, reads from the keyboard the entered
|
||||
* text until a newline character is detected, echoes the text to the screen,
|
||||
* and returns its value. Also handles user backspaces.
|
||||
*/
|
||||
function String readLine(String message) {
|
||||
var String s, b;
|
||||
var char c;
|
||||
let s = String.new(100);
|
||||
do Output.printString(message);
|
||||
while (true){
|
||||
let c = Keyboard.readChar();
|
||||
if (c = 128){
|
||||
return s;
|
||||
}
|
||||
else{
|
||||
if (c = 129){
|
||||
do s.eraseLastChar();
|
||||
}
|
||||
else{
|
||||
do s.appendChar(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the message on the screen, reads from the keyboard the entered
|
||||
* text until a newline character is detected, echoes the text to the screen,
|
||||
* and returns its integer value (until the first non-digit character in the
|
||||
* entered text is detected). Also handles user backspaces.
|
||||
*/
|
||||
function int readInt(String message) {
|
||||
var starting a;
|
||||
var int b;
|
||||
let a = Main.readLine_stolen(message);
|
||||
let b = String.intValue(a);
|
||||
do String.dispose(a);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
Executable
+156
@@ -0,0 +1,156 @@
|
||||
function Keyboard.init 0
|
||||
push constant 0
|
||||
pop static 0
|
||||
push constant 0
|
||||
return
|
||||
function Keyboard.keyPressed 0
|
||||
push static 0
|
||||
push constant 24576
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
return
|
||||
function Keyboard.readChar 2
|
||||
push constant 0
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
label L0
|
||||
push local 1
|
||||
push constant 0
|
||||
eq
|
||||
push local 0
|
||||
push constant 0
|
||||
gt
|
||||
or
|
||||
not
|
||||
if-goto L1
|
||||
call Keyboard.keyPressed 0
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L2
|
||||
push local 0
|
||||
pop local 1
|
||||
goto L3
|
||||
label L2
|
||||
label L3
|
||||
goto L0
|
||||
label L1
|
||||
call String.backSpace 0
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
return
|
||||
function Keyboard.readLine 3
|
||||
push constant 100
|
||||
call String.new 1
|
||||
pop local 0
|
||||
push argument 0
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
label L4
|
||||
push constant 1
|
||||
neg
|
||||
not
|
||||
if-goto L5
|
||||
call Keyboard.readChar 0
|
||||
pop local 2
|
||||
push local 2
|
||||
push constant 128
|
||||
eq
|
||||
not
|
||||
if-goto L6
|
||||
push local 0
|
||||
return
|
||||
goto L7
|
||||
label L6
|
||||
push local 2
|
||||
push constant 129
|
||||
eq
|
||||
not
|
||||
if-goto L8
|
||||
push local 0
|
||||
call String.eraseLastChar 1
|
||||
pop temp 0
|
||||
goto L9
|
||||
label L8
|
||||
push local 0
|
||||
push local 2
|
||||
call String.appendChar 2
|
||||
pop temp 0
|
||||
label L9
|
||||
label L7
|
||||
goto L4
|
||||
label L5
|
||||
function Keyboard.readInt 2
|
||||
push constant 100
|
||||
call String.new 1
|
||||
pop local 0
|
||||
push argument 0
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
label L10
|
||||
push constant 1
|
||||
neg
|
||||
not
|
||||
if-goto L11
|
||||
push local 1
|
||||
call Keyboard.readChar 1
|
||||
pop local 1
|
||||
push local 1
|
||||
push constant 128
|
||||
eq
|
||||
not
|
||||
if-goto L12
|
||||
push local 0
|
||||
call String.intValue 1
|
||||
return
|
||||
goto L13
|
||||
label L12
|
||||
push local 1
|
||||
push constant 129
|
||||
eq
|
||||
not
|
||||
if-goto L14
|
||||
push local 0
|
||||
call String.eraseLastChar 1
|
||||
pop temp 0
|
||||
goto L15
|
||||
label L14
|
||||
push local 1
|
||||
push constant 47
|
||||
gt
|
||||
push local 1
|
||||
push constant 57
|
||||
lt
|
||||
and
|
||||
not
|
||||
if-goto L16
|
||||
push local 0
|
||||
push local 1
|
||||
call String.appendChar 2
|
||||
pop temp 0
|
||||
goto L17
|
||||
label L16
|
||||
label L17
|
||||
push local 1
|
||||
push constant 45
|
||||
eq
|
||||
not
|
||||
if-goto L18
|
||||
push local 0
|
||||
push local 1
|
||||
call String.appendChar 2
|
||||
pop temp 0
|
||||
goto L19
|
||||
label L18
|
||||
label L19
|
||||
label L15
|
||||
label L13
|
||||
goto L10
|
||||
label L11
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Executable
+93
@@ -0,0 +1,93 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/KeyboardTest/Main.jack
|
||||
|
||||
/** Test program for the OS Keyboard class. */
|
||||
class Main {
|
||||
|
||||
/** Gets input from the user and verifies its contents. */
|
||||
function void main() {
|
||||
var char c, key;
|
||||
var String s;
|
||||
var int i;
|
||||
var boolean ok;
|
||||
|
||||
let ok = false;
|
||||
do Output.printString("keyPressed test:");
|
||||
do Output.println();
|
||||
while (~ok) {
|
||||
do Output.printString("Please press the 'Page Down' key");
|
||||
while (key = 0) {
|
||||
let key = Keyboard.keyPressed();
|
||||
}
|
||||
let c = key;
|
||||
while (~(key = 0)) {
|
||||
let key = Keyboard.keyPressed();
|
||||
}
|
||||
|
||||
do Output.println();
|
||||
|
||||
if (c = 137) {
|
||||
do Output.printString("ok");
|
||||
do Output.println();
|
||||
let ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
let ok = false;
|
||||
do Output.printString("readChar test:");
|
||||
do Output.println();
|
||||
do Output.printString("(Verify that the pressed character is echoed to the screen)");
|
||||
do Output.println();
|
||||
while (~ok) {
|
||||
do Output.printString("Please press the number '3': ");
|
||||
let c = Keyboard.readChar();
|
||||
|
||||
do Output.println();
|
||||
|
||||
if (c = 51) {
|
||||
do Output.printString("ok");
|
||||
do Output.println();
|
||||
let ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
let ok = false;
|
||||
do Output.printString("readLine test:");
|
||||
do Output.println();
|
||||
do Output.printString("(Verify echo and usage of 'backspace')");
|
||||
do Output.println();
|
||||
while (~ok) {
|
||||
let s = Keyboard.readLine("Please type 'JACK' and press enter: ");
|
||||
|
||||
if (s.length() = 4) {
|
||||
if ((s.charAt(0) = 74) & (s.charAt(1) = 65) & (s.charAt(2) = 67) & (s.charAt(3) = 75)) {
|
||||
do Output.printString("ok");
|
||||
do Output.println();
|
||||
let ok = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let ok = false;
|
||||
do Output.printString("readInt test:");
|
||||
do Output.println();
|
||||
do Output.printString("(Verify echo and usage of 'backspace')");
|
||||
do Output.println();
|
||||
while (~ok) {
|
||||
let i = Keyboard.readInt("Please type '-32123' and press enter: ");
|
||||
|
||||
if (i = (-32123)) {
|
||||
do Output.printString("ok");
|
||||
do Output.println();
|
||||
let ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
do Output.println();
|
||||
do Output.printString("Test completed successfully");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+954
@@ -0,0 +1,954 @@
|
||||
function Main.main 5
|
||||
push constant 0
|
||||
pop local 4
|
||||
push constant 16
|
||||
call String.new 1
|
||||
push constant 107
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 121
|
||||
call String.appendChar 2
|
||||
push constant 80
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
label L0
|
||||
push local 4
|
||||
not
|
||||
not
|
||||
if-goto L1
|
||||
push constant 32
|
||||
call String.new 1
|
||||
push constant 80
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 80
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 103
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 68
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 119
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 107
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 121
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
label L2
|
||||
push local 1
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L3
|
||||
call Keyboard.keyPressed 0
|
||||
pop local 1
|
||||
goto L2
|
||||
label L3
|
||||
push local 1
|
||||
pop local 0
|
||||
label L4
|
||||
push local 1
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
not
|
||||
if-goto L5
|
||||
call Keyboard.keyPressed 0
|
||||
pop local 1
|
||||
goto L4
|
||||
label L5
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 137
|
||||
eq
|
||||
not
|
||||
if-goto L6
|
||||
push constant 2
|
||||
call String.new 1
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 107
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 1
|
||||
neg
|
||||
pop local 4
|
||||
goto L7
|
||||
label L6
|
||||
label L7
|
||||
goto L0
|
||||
label L1
|
||||
push constant 0
|
||||
pop local 4
|
||||
push constant 14
|
||||
call String.new 1
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 67
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 59
|
||||
call String.new 1
|
||||
push constant 40
|
||||
call String.appendChar 2
|
||||
push constant 86
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 102
|
||||
call String.appendChar 2
|
||||
push constant 121
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 41
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
label L8
|
||||
push local 4
|
||||
not
|
||||
not
|
||||
if-goto L9
|
||||
push constant 29
|
||||
call String.new 1
|
||||
push constant 80
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 109
|
||||
call String.appendChar 2
|
||||
push constant 98
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 51
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Keyboard.readChar 0
|
||||
pop local 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 51
|
||||
eq
|
||||
not
|
||||
if-goto L10
|
||||
push constant 2
|
||||
call String.new 1
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 107
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 1
|
||||
neg
|
||||
pop local 4
|
||||
goto L11
|
||||
label L10
|
||||
label L11
|
||||
goto L8
|
||||
label L9
|
||||
push constant 0
|
||||
pop local 4
|
||||
push constant 14
|
||||
call String.new 1
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 76
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 38
|
||||
call String.new 1
|
||||
push constant 40
|
||||
call String.appendChar 2
|
||||
push constant 86
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 102
|
||||
call String.appendChar 2
|
||||
push constant 121
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 103
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 102
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 98
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 107
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 41
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
label L12
|
||||
push local 4
|
||||
not
|
||||
not
|
||||
if-goto L13
|
||||
push constant 36
|
||||
call String.new 1
|
||||
push constant 80
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 121
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 74
|
||||
call String.appendChar 2
|
||||
push constant 65
|
||||
call String.appendChar 2
|
||||
push constant 67
|
||||
call String.appendChar 2
|
||||
push constant 75
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Keyboard.readLine 1
|
||||
pop local 2
|
||||
push local 2
|
||||
call String.length 1
|
||||
push constant 4
|
||||
eq
|
||||
not
|
||||
if-goto L14
|
||||
push local 2
|
||||
push constant 0
|
||||
call String.charAt 2
|
||||
push constant 74
|
||||
eq
|
||||
push local 2
|
||||
push constant 1
|
||||
call String.charAt 2
|
||||
push constant 65
|
||||
eq
|
||||
and
|
||||
push local 2
|
||||
push constant 2
|
||||
call String.charAt 2
|
||||
push constant 67
|
||||
eq
|
||||
and
|
||||
push local 2
|
||||
push constant 3
|
||||
call String.charAt 2
|
||||
push constant 75
|
||||
eq
|
||||
and
|
||||
not
|
||||
if-goto L15
|
||||
push constant 2
|
||||
call String.new 1
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 107
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 1
|
||||
neg
|
||||
pop local 4
|
||||
goto L16
|
||||
label L15
|
||||
label L16
|
||||
goto L17
|
||||
label L14
|
||||
label L17
|
||||
goto L12
|
||||
label L13
|
||||
push constant 0
|
||||
pop local 4
|
||||
push constant 13
|
||||
call String.new 1
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 73
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 38
|
||||
call String.new 1
|
||||
push constant 40
|
||||
call String.appendChar 2
|
||||
push constant 86
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 102
|
||||
call String.appendChar 2
|
||||
push constant 121
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 103
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 102
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 98
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 107
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 41
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
label L18
|
||||
push local 4
|
||||
not
|
||||
not
|
||||
if-goto L19
|
||||
push constant 38
|
||||
call String.new 1
|
||||
push constant 80
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 121
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 45
|
||||
call String.appendChar 2
|
||||
push constant 51
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 49
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 51
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Keyboard.readInt 1
|
||||
pop local 3
|
||||
push local 3
|
||||
push constant 32123
|
||||
neg
|
||||
eq
|
||||
not
|
||||
if-goto L20
|
||||
push constant 2
|
||||
call String.new 1
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 107
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 1
|
||||
neg
|
||||
pop local 4
|
||||
goto L21
|
||||
label L20
|
||||
label L21
|
||||
goto L18
|
||||
label L19
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 27
|
||||
call String.new 1
|
||||
push constant 84
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 109
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 102
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 121
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+143
@@ -0,0 +1,143 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Math.jack
|
||||
|
||||
/**
|
||||
* A library of commonly used mathematical functions.
|
||||
* Note: Jack compilers implement multiplication and division using OS method calls.
|
||||
*/
|
||||
class Math {
|
||||
static Array st;
|
||||
static int division_tmp, f;
|
||||
|
||||
/** Initializes the library. */
|
||||
function void init() {
|
||||
var int a;
|
||||
let st = Array.new(16);
|
||||
let st[0] = 1;
|
||||
while (a < 15){
|
||||
let a = a + 1;
|
||||
let st[a] = st[a - 1] + st[a - 1];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the absolute value of x. */
|
||||
function int abs(int x) {
|
||||
if (x > 0){
|
||||
return x;
|
||||
}
|
||||
return -x;
|
||||
}
|
||||
|
||||
/** Returns the product of x and y.
|
||||
* When a Jack compiler detects the multiplication operator '*' in the
|
||||
* program's code, it handles it by invoking this method. In other words,
|
||||
* the Jack expressions x*y and multiply(x,y) return the same value.
|
||||
*/
|
||||
function int multiply(int x, int y) {
|
||||
var int sum, temp, y_comp, i, neg;
|
||||
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
|
||||
let x = Math.abs(x);
|
||||
let y = Math.abs(y);
|
||||
if (x < y){
|
||||
let temp = x;
|
||||
let x = y;
|
||||
let y = temp;
|
||||
}
|
||||
if (y = 1){
|
||||
if(neg){
|
||||
return -x;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
while((y_comp - 1) < (y - 1)){
|
||||
if ((st[i] & y) > 0) {
|
||||
let sum = sum + x;
|
||||
let y_comp = y_comp + st[i];
|
||||
}
|
||||
let x = x + x;
|
||||
let i = i + 1;
|
||||
}
|
||||
if(neg){
|
||||
let sum = -sum;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/** Returns the integer part of x/y.
|
||||
* When a Jack compiler detects the multiplication operator '/' in the
|
||||
* program's code, it handles it by invoking this method. In other words,
|
||||
* the Jack expressions x/y and divide(x,y) return the same value.
|
||||
*/
|
||||
function int divide(int x, int y) {
|
||||
var int q, neg;
|
||||
if (f = 0){
|
||||
let division_tmp = 0;
|
||||
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
|
||||
let x = Math.abs(x);
|
||||
let y = Math.abs(y);
|
||||
if (y = 0){
|
||||
do Sys.error(3);
|
||||
}
|
||||
let f = 1;
|
||||
}
|
||||
if ((y > x) | (y < 0)){
|
||||
return 0;
|
||||
}
|
||||
let q = Math.divide(x, y + y);
|
||||
let f = 0;
|
||||
let q = Math.abs(q);
|
||||
if ((q & 1) = 1){
|
||||
let division_tmp = division_tmp + y + y;
|
||||
}
|
||||
if (x - division_tmp < y){
|
||||
if (neg){
|
||||
return -(q + q);
|
||||
}
|
||||
return q + q;
|
||||
}
|
||||
else{
|
||||
if (neg){
|
||||
return -(q + q + 1);
|
||||
}
|
||||
return q + q + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the integer part of the square root of x. */
|
||||
function int sqrt(int x) {
|
||||
var int j, b, d, y;
|
||||
|
||||
if (x < 0){
|
||||
do Sys.error(4);
|
||||
}
|
||||
let j = 7;
|
||||
while (j > -1){
|
||||
let d = y + st[j];
|
||||
let b = d * d;
|
||||
if ((~(b > x)) & (b > 0)){
|
||||
let y = d;
|
||||
}
|
||||
let j = j - 1;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/** Returns the greater number. */
|
||||
function int max(int a, int b) {
|
||||
if (a > b){
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/** Returns the smaller number. */
|
||||
function int min(int a, int b) {
|
||||
if (a < b){
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
function Array.new 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 2
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
call Memory.alloc 1
|
||||
return
|
||||
function Array.dispose 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push pointer 0
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+102
@@ -0,0 +1,102 @@
|
||||
function Keyboard.init 0
|
||||
push constant 0
|
||||
return
|
||||
function Keyboard.keyPressed 0
|
||||
push constant 24576
|
||||
call Memory.peek 1
|
||||
return
|
||||
function Keyboard.readChar 2
|
||||
push constant 0
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
label WHILE_EXP0
|
||||
push local 1
|
||||
push constant 0
|
||||
eq
|
||||
push local 0
|
||||
push constant 0
|
||||
gt
|
||||
or
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
call Keyboard.keyPressed 0
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 0
|
||||
gt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push local 0
|
||||
pop local 1
|
||||
label IF_FALSE0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
call String.backSpace 0
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
return
|
||||
function Keyboard.readLine 5
|
||||
push constant 80
|
||||
call String.new 1
|
||||
pop local 3
|
||||
push argument 0
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call String.newLine 0
|
||||
pop local 1
|
||||
call String.backSpace 0
|
||||
pop local 2
|
||||
label WHILE_EXP0
|
||||
push local 4
|
||||
not
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
call Keyboard.readChar 0
|
||||
pop local 0
|
||||
push local 0
|
||||
push local 1
|
||||
eq
|
||||
pop local 4
|
||||
push local 4
|
||||
not
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push local 0
|
||||
push local 2
|
||||
eq
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push local 3
|
||||
call String.eraseLastChar 1
|
||||
pop temp 0
|
||||
goto IF_END1
|
||||
label IF_FALSE1
|
||||
push local 3
|
||||
push local 0
|
||||
call String.appendChar 2
|
||||
pop local 3
|
||||
label IF_END1
|
||||
label IF_FALSE0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push local 3
|
||||
return
|
||||
function Keyboard.readInt 2
|
||||
push argument 0
|
||||
call Keyboard.readLine 1
|
||||
pop local 0
|
||||
push local 0
|
||||
call String.intValue 1
|
||||
pop local 1
|
||||
push local 0
|
||||
call String.dispose 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
return
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/MathTest/Main.jack
|
||||
|
||||
/** Test program for the OS Math class. */
|
||||
class Main {
|
||||
|
||||
/** Performs various mathematical operations, using calls to the Math class methods. */
|
||||
function void main() {
|
||||
var Array r; // stores the test results;
|
||||
|
||||
let r = 8000;
|
||||
|
||||
let r[0] = 2 * 3; // 6
|
||||
let r[1] = r[0] * (-30); // 6 * (-30) = -180
|
||||
let r[2] = r[1] * 100; // (-180) * 100 = -18000
|
||||
let r[3] = 1 * r[2]; // 1 * (-18000) = -18000
|
||||
let r[4] = r[3] * 0; // 0
|
||||
|
||||
let r[5] = 9 / 3; // 3
|
||||
let r[6] = (-18000) / 6; // -3000
|
||||
let r[7] = 32766 / (-32767); // 0
|
||||
|
||||
let r[8] = Math.sqrt(9); // 3
|
||||
let r[9] = Math.sqrt(32767); // 181
|
||||
|
||||
let r[10] = Math.min(345, 123); // 123
|
||||
let r[11] = Math.max(123, -345); // 123
|
||||
let r[12] = Math.abs(27); // 27
|
||||
let r[13] = Math.abs(-32767); // 32767
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+162
@@ -0,0 +1,162 @@
|
||||
function Main.main 1
|
||||
push constant 8000
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 0
|
||||
push constant 2
|
||||
push constant 3
|
||||
call Math.multiply 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
push local 0
|
||||
push constant 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 30
|
||||
neg
|
||||
call Math.multiply 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 2
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 100
|
||||
call Math.multiply 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 3
|
||||
push constant 1
|
||||
push local 0
|
||||
push constant 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
call Math.multiply 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 4
|
||||
push local 0
|
||||
push constant 3
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 0
|
||||
call Math.multiply 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 5
|
||||
push constant 9
|
||||
push constant 3
|
||||
call Math.divide 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 6
|
||||
push constant 18000
|
||||
neg
|
||||
push constant 6
|
||||
call Math.divide 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 7
|
||||
push constant 32766
|
||||
push constant 32767
|
||||
neg
|
||||
call Math.divide 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 8
|
||||
push constant 9
|
||||
call Math.sqrt 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 9
|
||||
push constant 32767
|
||||
call Math.sqrt 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 10
|
||||
push constant 345
|
||||
push constant 123
|
||||
call Math.min 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 11
|
||||
push constant 123
|
||||
push constant 345
|
||||
neg
|
||||
call Math.max 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 12
|
||||
push constant 27
|
||||
call Math.abs 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 13
|
||||
push constant 32767
|
||||
neg
|
||||
call Math.abs 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+143
@@ -0,0 +1,143 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Math.jack
|
||||
|
||||
/**
|
||||
* A library of commonly used mathematical functions.
|
||||
* Note: Jack compilers implement multiplication and division using OS method calls.
|
||||
*/
|
||||
class Math {
|
||||
static Array st;
|
||||
static int division_tmp, f;
|
||||
|
||||
/** Initializes the library. */
|
||||
function void init() {
|
||||
var int a;
|
||||
let st = Array.new(16);
|
||||
let st[0] = 1;
|
||||
while (a < 15){
|
||||
let a = a + 1;
|
||||
let st[a] = st[a - 1] + st[a - 1];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the absolute value of x. */
|
||||
function int abs(int x) {
|
||||
if (x > 0){
|
||||
return x;
|
||||
}
|
||||
return -x;
|
||||
}
|
||||
|
||||
/** Returns the product of x and y.
|
||||
* When a Jack compiler detects the multiplication operator '*' in the
|
||||
* program's code, it handles it by invoking this method. In other words,
|
||||
* the Jack expressions x*y and multiply(x,y) return the same value.
|
||||
*/
|
||||
function int multiply(int x, int y) {
|
||||
var int sum, temp, y_comp, i, neg;
|
||||
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
|
||||
let x = Math.abs(x);
|
||||
let y = Math.abs(y);
|
||||
if (x < y){
|
||||
let temp = x;
|
||||
let x = y;
|
||||
let y = temp;
|
||||
}
|
||||
if (y = 1){
|
||||
if(neg){
|
||||
return -x;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
while((y_comp - 1) < (y - 1)){
|
||||
if ((st[i] & y) > 0) {
|
||||
let sum = sum + x;
|
||||
let y_comp = y_comp + st[i];
|
||||
}
|
||||
let x = x + x;
|
||||
let i = i + 1;
|
||||
}
|
||||
if(neg){
|
||||
let sum = -sum;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/** Returns the integer part of x/y.
|
||||
* When a Jack compiler detects the multiplication operator '/' in the
|
||||
* program's code, it handles it by invoking this method. In other words,
|
||||
* the Jack expressions x/y and divide(x,y) return the same value.
|
||||
*/
|
||||
function int divide(int x, int y) {
|
||||
var int q, neg;
|
||||
if (f = 0){
|
||||
let division_tmp = 0;
|
||||
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
|
||||
let x = Math.abs(x);
|
||||
let y = Math.abs(y);
|
||||
if (y = 0){
|
||||
do Sys.error(3);
|
||||
}
|
||||
let f = 1;
|
||||
}
|
||||
if ((y > x) | (y < 0)){
|
||||
return 0;
|
||||
}
|
||||
let q = divide(x, y + y);
|
||||
let f = 0;
|
||||
let q = Math.abs(q);
|
||||
if ((q & 1) = 1){
|
||||
let division_tmp = division_tmp + y + y;
|
||||
}
|
||||
if (x - division_tmp < y){
|
||||
if (neg){
|
||||
return -(q + q);
|
||||
}
|
||||
return q + q;
|
||||
}
|
||||
else{
|
||||
if (neg){
|
||||
return -(q + q + 1);
|
||||
}
|
||||
return q + q + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the integer part of the square root of x. */
|
||||
function int sqrt(int x) {
|
||||
var int j, b, d, y;
|
||||
|
||||
if (x < 0){
|
||||
do Sys.error(4);
|
||||
}
|
||||
let j = 7;
|
||||
while (j > -1){
|
||||
let d = y + st[j];
|
||||
let b = d * d;
|
||||
if ((~(b > x)) & (b > 0)){
|
||||
let y = d;
|
||||
}
|
||||
let j = j - 1;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/** Returns the greater number. */
|
||||
function int max(int a, int b) {
|
||||
if (a > b){
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/** Returns the smaller number. */
|
||||
function int min(int a, int b) {
|
||||
if (a < b){
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
Executable
+388
@@ -0,0 +1,388 @@
|
||||
function Math.init 1
|
||||
push constant 16
|
||||
call Array.new 1
|
||||
pop static 0
|
||||
push static 0
|
||||
push constant 0
|
||||
push constant 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
label L0
|
||||
push local 0
|
||||
push constant 15
|
||||
lt
|
||||
not
|
||||
if-goto L1
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
push static 0
|
||||
push local 0
|
||||
push static 0
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push static 0
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
goto L0
|
||||
label L1
|
||||
push constant 0
|
||||
return
|
||||
function Math.abs 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L2
|
||||
push argument 0
|
||||
return
|
||||
goto L3
|
||||
label L2
|
||||
label L3
|
||||
push argument 0
|
||||
neg
|
||||
return
|
||||
function Math.multiply 5
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 1
|
||||
push constant 0
|
||||
gt
|
||||
and
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
and
|
||||
or
|
||||
pop local 4
|
||||
push argument 0
|
||||
call Math.abs 1
|
||||
pop argument 0
|
||||
push argument 1
|
||||
call Math.abs 1
|
||||
pop argument 1
|
||||
push argument 0
|
||||
push argument 1
|
||||
lt
|
||||
not
|
||||
if-goto L4
|
||||
push argument 0
|
||||
pop local 1
|
||||
push argument 1
|
||||
pop argument 0
|
||||
push local 1
|
||||
pop argument 1
|
||||
goto L5
|
||||
label L4
|
||||
label L5
|
||||
push argument 1
|
||||
push constant 1
|
||||
eq
|
||||
not
|
||||
if-goto L6
|
||||
push local 4
|
||||
not
|
||||
if-goto L7
|
||||
push argument 0
|
||||
neg
|
||||
return
|
||||
goto L8
|
||||
label L7
|
||||
label L8
|
||||
push argument 0
|
||||
return
|
||||
goto L9
|
||||
label L6
|
||||
label L9
|
||||
label L10
|
||||
push local 2
|
||||
push constant 1
|
||||
sub
|
||||
push argument 1
|
||||
push constant 1
|
||||
sub
|
||||
lt
|
||||
not
|
||||
if-goto L11
|
||||
push static 0
|
||||
push local 3
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 1
|
||||
and
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L12
|
||||
push local 0
|
||||
push argument 0
|
||||
add
|
||||
pop local 0
|
||||
push local 2
|
||||
push static 0
|
||||
push local 3
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop local 2
|
||||
goto L13
|
||||
label L12
|
||||
label L13
|
||||
push argument 0
|
||||
push argument 0
|
||||
add
|
||||
pop argument 0
|
||||
push local 3
|
||||
push constant 1
|
||||
add
|
||||
pop local 3
|
||||
goto L10
|
||||
label L11
|
||||
push local 4
|
||||
not
|
||||
if-goto L14
|
||||
push local 0
|
||||
neg
|
||||
pop local 0
|
||||
goto L15
|
||||
label L14
|
||||
label L15
|
||||
push local 0
|
||||
return
|
||||
function Math.divide 2
|
||||
push static 2
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L16
|
||||
push constant 0
|
||||
pop static 1
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 1
|
||||
push constant 0
|
||||
gt
|
||||
and
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
and
|
||||
or
|
||||
pop local 1
|
||||
push argument 0
|
||||
call Math.abs 1
|
||||
pop argument 0
|
||||
push argument 1
|
||||
call Math.abs 1
|
||||
pop argument 1
|
||||
push argument 1
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L17
|
||||
push constant 3
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L18
|
||||
label L17
|
||||
label L18
|
||||
push constant 1
|
||||
pop static 2
|
||||
goto L19
|
||||
label L16
|
||||
label L19
|
||||
push argument 1
|
||||
push argument 0
|
||||
gt
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
not
|
||||
if-goto L20
|
||||
push constant 0
|
||||
return
|
||||
goto L21
|
||||
label L20
|
||||
label L21
|
||||
push argument 0
|
||||
push argument 1
|
||||
push argument 1
|
||||
add
|
||||
call Math.divide 2
|
||||
pop local 0
|
||||
push constant 0
|
||||
pop static 2
|
||||
push local 0
|
||||
call Math.abs 1
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 1
|
||||
and
|
||||
push constant 1
|
||||
eq
|
||||
not
|
||||
if-goto L22
|
||||
push static 1
|
||||
push argument 1
|
||||
add
|
||||
push argument 1
|
||||
add
|
||||
pop static 1
|
||||
goto L23
|
||||
label L22
|
||||
label L23
|
||||
push argument 0
|
||||
push static 1
|
||||
sub
|
||||
push argument 1
|
||||
lt
|
||||
not
|
||||
if-goto L24
|
||||
push local 1
|
||||
not
|
||||
if-goto L25
|
||||
push local 0
|
||||
push local 0
|
||||
add
|
||||
neg
|
||||
return
|
||||
goto L26
|
||||
label L25
|
||||
label L26
|
||||
push local 0
|
||||
push local 0
|
||||
add
|
||||
return
|
||||
goto L27
|
||||
label L24
|
||||
push local 1
|
||||
not
|
||||
if-goto L28
|
||||
push local 0
|
||||
push local 0
|
||||
add
|
||||
push constant 1
|
||||
add
|
||||
neg
|
||||
return
|
||||
goto L29
|
||||
label L28
|
||||
label L29
|
||||
push local 0
|
||||
push local 0
|
||||
add
|
||||
push constant 1
|
||||
add
|
||||
return
|
||||
label L27
|
||||
function Math.sqrt 4
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L30
|
||||
push constant 4
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L31
|
||||
label L30
|
||||
label L31
|
||||
push constant 7
|
||||
pop local 0
|
||||
label L32
|
||||
push local 0
|
||||
push constant 1
|
||||
neg
|
||||
gt
|
||||
not
|
||||
if-goto L33
|
||||
push local 3
|
||||
push static 0
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop local 2
|
||||
push local 2
|
||||
push local 2
|
||||
call Math.multiply 2
|
||||
pop local 1
|
||||
push local 1
|
||||
push argument 0
|
||||
gt
|
||||
not
|
||||
push local 1
|
||||
push constant 0
|
||||
gt
|
||||
and
|
||||
not
|
||||
if-goto L34
|
||||
push local 2
|
||||
pop local 3
|
||||
goto L35
|
||||
label L34
|
||||
label L35
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 0
|
||||
goto L32
|
||||
label L33
|
||||
push local 3
|
||||
return
|
||||
function Math.max 0
|
||||
push argument 0
|
||||
push argument 1
|
||||
gt
|
||||
not
|
||||
if-goto L36
|
||||
push argument 0
|
||||
return
|
||||
goto L37
|
||||
label L36
|
||||
label L37
|
||||
push argument 1
|
||||
return
|
||||
function Math.min 0
|
||||
push argument 0
|
||||
push argument 1
|
||||
lt
|
||||
not
|
||||
if-goto L38
|
||||
push argument 0
|
||||
return
|
||||
goto L39
|
||||
label L38
|
||||
label L39
|
||||
push argument 1
|
||||
return
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|RAM[8004]|RAM[8005]|RAM[8006]|RAM[8007]|RAM[8008]|RAM[8009]|RAM[8010]|RAM[8011]|RAM[8012]|RAM[8013]|
|
||||
| 6 | -180 | -18000 | -18000 | 0 | 3 | -3000 | 0 | 3 | 181 | 123 | 123 | 27 | 32767 |
|
||||
Executable
Executable
+15
@@ -0,0 +1,15 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/MathTest/MathTest.tst
|
||||
|
||||
load,
|
||||
output-file MathTest.out,
|
||||
compare-to MathTest.cmp,
|
||||
output-list RAM[8000]%D2.6.1 RAM[8001]%D2.6.1 RAM[8002]%D2.6.1 RAM[8003]%D2.6.1 RAM[8004]%D2.6.1 RAM[8005]%D2.6.1 RAM[8006]%D2.6.1 RAM[8007]%D2.6.1 RAM[8008]%D2.6.1 RAM[8009]%D2.6.1 RAM[8010]%D2.6.1 RAM[8011]%D2.6.1 RAM[8012]%D2.6.1 RAM[8013]%D2.6.1;
|
||||
|
||||
repeat 1150000 {
|
||||
vmstep;
|
||||
}
|
||||
|
||||
output;
|
||||
Executable
+376
@@ -0,0 +1,376 @@
|
||||
function Memory.init 0
|
||||
push constant 0
|
||||
pop static 0
|
||||
push constant 2048
|
||||
push static 0
|
||||
add
|
||||
push constant 14334
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push constant 2049
|
||||
push static 0
|
||||
add
|
||||
push constant 2050
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
function Memory.peek 0
|
||||
push argument 0
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
return
|
||||
function Memory.poke 0
|
||||
push argument 0
|
||||
push static 0
|
||||
add
|
||||
push argument 1
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
function Memory.alloc 2
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 5
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push constant 1
|
||||
pop argument 0
|
||||
label IF_FALSE1
|
||||
push constant 2048
|
||||
pop local 0
|
||||
label WHILE_EXP0
|
||||
push local 0
|
||||
push constant 16383
|
||||
lt
|
||||
push constant 0
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 0
|
||||
lt
|
||||
and
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push constant 1
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop local 1
|
||||
push constant 0
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 0
|
||||
eq
|
||||
push local 1
|
||||
push constant 16382
|
||||
gt
|
||||
or
|
||||
push constant 0
|
||||
push local 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 0
|
||||
eq
|
||||
or
|
||||
if-goto IF_TRUE2
|
||||
goto IF_FALSE2
|
||||
label IF_TRUE2
|
||||
push local 1
|
||||
pop local 0
|
||||
goto IF_END2
|
||||
label IF_FALSE2
|
||||
push constant 0
|
||||
push local 0
|
||||
add
|
||||
push constant 1
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 0
|
||||
sub
|
||||
push constant 0
|
||||
push local 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push constant 1
|
||||
push local 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 1
|
||||
push constant 2
|
||||
add
|
||||
eq
|
||||
if-goto IF_TRUE3
|
||||
goto IF_FALSE3
|
||||
label IF_TRUE3
|
||||
push constant 1
|
||||
push local 0
|
||||
add
|
||||
push local 0
|
||||
push constant 2
|
||||
add
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
goto IF_END3
|
||||
label IF_FALSE3
|
||||
push constant 1
|
||||
push local 0
|
||||
add
|
||||
push constant 1
|
||||
push local 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
label IF_END3
|
||||
label IF_END2
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push local 0
|
||||
push argument 0
|
||||
add
|
||||
push constant 16379
|
||||
gt
|
||||
if-goto IF_TRUE4
|
||||
goto IF_FALSE4
|
||||
label IF_TRUE4
|
||||
push constant 6
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE4
|
||||
push constant 0
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 0
|
||||
push constant 2
|
||||
add
|
||||
gt
|
||||
if-goto IF_TRUE5
|
||||
goto IF_FALSE5
|
||||
label IF_TRUE5
|
||||
push argument 0
|
||||
push constant 2
|
||||
add
|
||||
push local 0
|
||||
add
|
||||
push constant 0
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 0
|
||||
sub
|
||||
push constant 2
|
||||
sub
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push constant 1
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 0
|
||||
push constant 2
|
||||
add
|
||||
eq
|
||||
if-goto IF_TRUE6
|
||||
goto IF_FALSE6
|
||||
label IF_TRUE6
|
||||
push argument 0
|
||||
push constant 3
|
||||
add
|
||||
push local 0
|
||||
add
|
||||
push local 0
|
||||
push argument 0
|
||||
add
|
||||
push constant 4
|
||||
add
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
goto IF_END6
|
||||
label IF_FALSE6
|
||||
push argument 0
|
||||
push constant 3
|
||||
add
|
||||
push local 0
|
||||
add
|
||||
push constant 1
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
label IF_END6
|
||||
push constant 1
|
||||
push local 0
|
||||
add
|
||||
push local 0
|
||||
push argument 0
|
||||
add
|
||||
push constant 2
|
||||
add
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
label IF_FALSE5
|
||||
push constant 0
|
||||
push local 0
|
||||
add
|
||||
push constant 0
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 2
|
||||
add
|
||||
return
|
||||
function Memory.deAlloc 2
|
||||
push argument 0
|
||||
push constant 2
|
||||
sub
|
||||
pop local 0
|
||||
push constant 1
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop local 1
|
||||
push constant 0
|
||||
push local 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 0
|
||||
push local 0
|
||||
add
|
||||
push constant 1
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 0
|
||||
sub
|
||||
push constant 2
|
||||
sub
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
goto IF_END0
|
||||
label IF_FALSE0
|
||||
push constant 0
|
||||
push local 0
|
||||
add
|
||||
push constant 1
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 0
|
||||
sub
|
||||
push constant 0
|
||||
push local 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push constant 1
|
||||
push local 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 1
|
||||
push constant 2
|
||||
add
|
||||
eq
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push constant 1
|
||||
push local 0
|
||||
add
|
||||
push local 0
|
||||
push constant 2
|
||||
add
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
goto IF_END1
|
||||
label IF_FALSE1
|
||||
push constant 1
|
||||
push local 0
|
||||
add
|
||||
push constant 1
|
||||
push local 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
label IF_END1
|
||||
label IF_END0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+1852
File diff suppressed because it is too large
Load Diff
Executable
+806
@@ -0,0 +1,806 @@
|
||||
function Screen.init 1
|
||||
push constant 16384
|
||||
pop static 1
|
||||
push constant 0
|
||||
not
|
||||
pop static 2
|
||||
push constant 17
|
||||
call Array.new 1
|
||||
pop static 0
|
||||
push constant 0
|
||||
push static 0
|
||||
add
|
||||
push constant 1
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
label WHILE_EXP0
|
||||
push local 0
|
||||
push constant 16
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
push local 0
|
||||
push static 0
|
||||
add
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.clearScreen 1
|
||||
label WHILE_EXP0
|
||||
push local 0
|
||||
push constant 8192
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 0
|
||||
push static 1
|
||||
add
|
||||
push constant 0
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.updateLocation 0
|
||||
push static 2
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push argument 0
|
||||
push static 1
|
||||
add
|
||||
push argument 0
|
||||
push static 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 1
|
||||
or
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
goto IF_END0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push static 1
|
||||
add
|
||||
push argument 0
|
||||
push static 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 1
|
||||
not
|
||||
and
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
label IF_END0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.setColor 0
|
||||
push argument 0
|
||||
pop static 2
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawPixel 3
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 0
|
||||
push constant 511
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 1
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 7
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push constant 16
|
||||
call Math.divide 2
|
||||
pop local 0
|
||||
push argument 0
|
||||
push local 0
|
||||
push constant 16
|
||||
call Math.multiply 2
|
||||
sub
|
||||
pop local 1
|
||||
push argument 1
|
||||
push constant 32
|
||||
call Math.multiply 2
|
||||
push local 0
|
||||
add
|
||||
pop local 2
|
||||
push local 2
|
||||
push local 1
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawConditional 0
|
||||
push argument 2
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push argument 1
|
||||
push argument 0
|
||||
call Screen.drawPixel 2
|
||||
pop temp 0
|
||||
goto IF_END0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push argument 1
|
||||
call Screen.drawPixel 2
|
||||
pop temp 0
|
||||
label IF_END0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawLine 11
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 2
|
||||
push constant 511
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 3
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 8
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 2
|
||||
push argument 0
|
||||
sub
|
||||
call Math.abs 1
|
||||
pop local 3
|
||||
push argument 3
|
||||
push argument 1
|
||||
sub
|
||||
call Math.abs 1
|
||||
pop local 2
|
||||
push local 3
|
||||
push local 2
|
||||
lt
|
||||
pop local 6
|
||||
push local 6
|
||||
push argument 3
|
||||
push argument 1
|
||||
lt
|
||||
and
|
||||
push local 6
|
||||
not
|
||||
push argument 2
|
||||
push argument 0
|
||||
lt
|
||||
and
|
||||
or
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push argument 0
|
||||
pop local 4
|
||||
push argument 2
|
||||
pop argument 0
|
||||
push local 4
|
||||
pop argument 2
|
||||
push argument 1
|
||||
pop local 4
|
||||
push argument 3
|
||||
pop argument 1
|
||||
push local 4
|
||||
pop argument 3
|
||||
label IF_FALSE1
|
||||
push local 6
|
||||
if-goto IF_TRUE2
|
||||
goto IF_FALSE2
|
||||
label IF_TRUE2
|
||||
push local 3
|
||||
pop local 4
|
||||
push local 2
|
||||
pop local 3
|
||||
push local 4
|
||||
pop local 2
|
||||
push argument 1
|
||||
pop local 1
|
||||
push argument 0
|
||||
pop local 0
|
||||
push argument 3
|
||||
pop local 8
|
||||
push argument 0
|
||||
push argument 2
|
||||
gt
|
||||
pop local 7
|
||||
goto IF_END2
|
||||
label IF_FALSE2
|
||||
push argument 0
|
||||
pop local 1
|
||||
push argument 1
|
||||
pop local 0
|
||||
push argument 2
|
||||
pop local 8
|
||||
push argument 1
|
||||
push argument 3
|
||||
gt
|
||||
pop local 7
|
||||
label IF_END2
|
||||
push constant 2
|
||||
push local 2
|
||||
call Math.multiply 2
|
||||
push local 3
|
||||
sub
|
||||
pop local 5
|
||||
push constant 2
|
||||
push local 2
|
||||
call Math.multiply 2
|
||||
pop local 9
|
||||
push constant 2
|
||||
push local 2
|
||||
push local 3
|
||||
sub
|
||||
call Math.multiply 2
|
||||
pop local 10
|
||||
push local 1
|
||||
push local 0
|
||||
push local 6
|
||||
call Screen.drawConditional 3
|
||||
pop temp 0
|
||||
label WHILE_EXP0
|
||||
push local 1
|
||||
push local 8
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 5
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE3
|
||||
goto IF_FALSE3
|
||||
label IF_TRUE3
|
||||
push local 5
|
||||
push local 9
|
||||
add
|
||||
pop local 5
|
||||
goto IF_END3
|
||||
label IF_FALSE3
|
||||
push local 5
|
||||
push local 10
|
||||
add
|
||||
pop local 5
|
||||
push local 7
|
||||
if-goto IF_TRUE4
|
||||
goto IF_FALSE4
|
||||
label IF_TRUE4
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 0
|
||||
goto IF_END4
|
||||
label IF_FALSE4
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
label IF_END4
|
||||
label IF_END3
|
||||
push local 1
|
||||
push constant 1
|
||||
add
|
||||
pop local 1
|
||||
push local 1
|
||||
push local 0
|
||||
push local 6
|
||||
call Screen.drawConditional 3
|
||||
pop temp 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawRectangle 9
|
||||
push argument 0
|
||||
push argument 2
|
||||
gt
|
||||
push argument 1
|
||||
push argument 3
|
||||
gt
|
||||
or
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 2
|
||||
push constant 511
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 3
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 9
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push constant 16
|
||||
call Math.divide 2
|
||||
pop local 3
|
||||
push argument 0
|
||||
push local 3
|
||||
push constant 16
|
||||
call Math.multiply 2
|
||||
sub
|
||||
pop local 7
|
||||
push argument 2
|
||||
push constant 16
|
||||
call Math.divide 2
|
||||
pop local 4
|
||||
push argument 2
|
||||
push local 4
|
||||
push constant 16
|
||||
call Math.multiply 2
|
||||
sub
|
||||
pop local 8
|
||||
push local 7
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 1
|
||||
sub
|
||||
not
|
||||
pop local 6
|
||||
push local 8
|
||||
push constant 1
|
||||
add
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 5
|
||||
push argument 1
|
||||
push constant 32
|
||||
call Math.multiply 2
|
||||
push local 3
|
||||
add
|
||||
pop local 0
|
||||
push local 4
|
||||
push local 3
|
||||
sub
|
||||
pop local 2
|
||||
label WHILE_EXP0
|
||||
push argument 1
|
||||
push argument 3
|
||||
gt
|
||||
not
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 0
|
||||
push local 2
|
||||
add
|
||||
pop local 1
|
||||
push local 2
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push local 0
|
||||
push local 5
|
||||
push local 6
|
||||
and
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
goto IF_END1
|
||||
label IF_FALSE1
|
||||
push local 0
|
||||
push local 6
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
label WHILE_EXP1
|
||||
push local 0
|
||||
push local 1
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END1
|
||||
push local 0
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
goto WHILE_EXP1
|
||||
label WHILE_END1
|
||||
push local 1
|
||||
push local 5
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
label IF_END1
|
||||
push argument 1
|
||||
push constant 1
|
||||
add
|
||||
pop argument 1
|
||||
push local 1
|
||||
push constant 32
|
||||
add
|
||||
push local 2
|
||||
sub
|
||||
pop local 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawHorizontal 11
|
||||
push argument 1
|
||||
push argument 2
|
||||
call Math.min 2
|
||||
pop local 7
|
||||
push argument 1
|
||||
push argument 2
|
||||
call Math.max 2
|
||||
pop local 8
|
||||
push argument 0
|
||||
push constant 1
|
||||
neg
|
||||
gt
|
||||
push argument 0
|
||||
push constant 256
|
||||
lt
|
||||
and
|
||||
push local 7
|
||||
push constant 512
|
||||
lt
|
||||
and
|
||||
push local 8
|
||||
push constant 1
|
||||
neg
|
||||
gt
|
||||
and
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push local 7
|
||||
push constant 0
|
||||
call Math.max 2
|
||||
pop local 7
|
||||
push local 8
|
||||
push constant 511
|
||||
call Math.min 2
|
||||
pop local 8
|
||||
push local 7
|
||||
push constant 16
|
||||
call Math.divide 2
|
||||
pop local 1
|
||||
push local 7
|
||||
push local 1
|
||||
push constant 16
|
||||
call Math.multiply 2
|
||||
sub
|
||||
pop local 9
|
||||
push local 8
|
||||
push constant 16
|
||||
call Math.divide 2
|
||||
pop local 2
|
||||
push local 8
|
||||
push local 2
|
||||
push constant 16
|
||||
call Math.multiply 2
|
||||
sub
|
||||
pop local 10
|
||||
push local 9
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 1
|
||||
sub
|
||||
not
|
||||
pop local 5
|
||||
push local 10
|
||||
push constant 1
|
||||
add
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 4
|
||||
push argument 0
|
||||
push constant 32
|
||||
call Math.multiply 2
|
||||
push local 1
|
||||
add
|
||||
pop local 0
|
||||
push local 2
|
||||
push local 1
|
||||
sub
|
||||
pop local 6
|
||||
push local 0
|
||||
push local 6
|
||||
add
|
||||
pop local 3
|
||||
push local 6
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push local 0
|
||||
push local 4
|
||||
push local 5
|
||||
and
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
goto IF_END1
|
||||
label IF_FALSE1
|
||||
push local 0
|
||||
push local 5
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
label WHILE_EXP0
|
||||
push local 0
|
||||
push local 3
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 0
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push local 3
|
||||
push local 4
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
label IF_END1
|
||||
label IF_FALSE0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawSymetric 0
|
||||
push argument 1
|
||||
push argument 3
|
||||
sub
|
||||
push argument 0
|
||||
push argument 2
|
||||
add
|
||||
push argument 0
|
||||
push argument 2
|
||||
sub
|
||||
call Screen.drawHorizontal 3
|
||||
pop temp 0
|
||||
push argument 1
|
||||
push argument 3
|
||||
add
|
||||
push argument 0
|
||||
push argument 2
|
||||
add
|
||||
push argument 0
|
||||
push argument 2
|
||||
sub
|
||||
call Screen.drawHorizontal 3
|
||||
pop temp 0
|
||||
push argument 1
|
||||
push argument 2
|
||||
sub
|
||||
push argument 0
|
||||
push argument 3
|
||||
sub
|
||||
push argument 0
|
||||
push argument 3
|
||||
add
|
||||
call Screen.drawHorizontal 3
|
||||
pop temp 0
|
||||
push argument 1
|
||||
push argument 2
|
||||
add
|
||||
push argument 0
|
||||
push argument 3
|
||||
sub
|
||||
push argument 0
|
||||
push argument 3
|
||||
add
|
||||
call Screen.drawHorizontal 3
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawCircle 3
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 0
|
||||
push constant 511
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 1
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 12
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push argument 2
|
||||
sub
|
||||
push constant 0
|
||||
lt
|
||||
push argument 0
|
||||
push argument 2
|
||||
add
|
||||
push constant 511
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push argument 2
|
||||
sub
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 1
|
||||
push argument 2
|
||||
add
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push constant 13
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE1
|
||||
push argument 2
|
||||
pop local 1
|
||||
push constant 1
|
||||
push argument 2
|
||||
sub
|
||||
pop local 2
|
||||
push argument 0
|
||||
push argument 1
|
||||
push local 0
|
||||
push local 1
|
||||
call Screen.drawSymetric 4
|
||||
pop temp 0
|
||||
label WHILE_EXP0
|
||||
push local 1
|
||||
push local 0
|
||||
gt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 2
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE2
|
||||
goto IF_FALSE2
|
||||
label IF_TRUE2
|
||||
push local 2
|
||||
push constant 2
|
||||
push local 0
|
||||
call Math.multiply 2
|
||||
add
|
||||
push constant 3
|
||||
add
|
||||
pop local 2
|
||||
goto IF_END2
|
||||
label IF_FALSE2
|
||||
push local 2
|
||||
push constant 2
|
||||
push local 0
|
||||
push local 1
|
||||
sub
|
||||
call Math.multiply 2
|
||||
add
|
||||
push constant 5
|
||||
add
|
||||
pop local 2
|
||||
push local 1
|
||||
push constant 1
|
||||
sub
|
||||
pop local 1
|
||||
label IF_END2
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
push argument 0
|
||||
push argument 1
|
||||
push local 0
|
||||
push local 1
|
||||
call Screen.drawSymetric 4
|
||||
pop temp 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+393
@@ -0,0 +1,393 @@
|
||||
function String.new 0
|
||||
push constant 3
|
||||
call Memory.alloc 1
|
||||
pop pointer 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 14
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push argument 0
|
||||
call Array.new 1
|
||||
pop this 1
|
||||
label IF_FALSE1
|
||||
push argument 0
|
||||
pop this 0
|
||||
push constant 0
|
||||
pop this 2
|
||||
push pointer 0
|
||||
return
|
||||
function String.dispose 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
push constant 0
|
||||
gt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push this 1
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push pointer 0
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function String.length 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 2
|
||||
return
|
||||
function String.charAt 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
push argument 1
|
||||
push this 2
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push this 2
|
||||
eq
|
||||
or
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 15
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 1
|
||||
push this 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
return
|
||||
function String.setCharAt 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
push argument 1
|
||||
push this 2
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push this 2
|
||||
eq
|
||||
or
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 16
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 1
|
||||
push this 1
|
||||
add
|
||||
push argument 2
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
function String.appendChar 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 2
|
||||
push this 0
|
||||
eq
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 17
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push this 2
|
||||
push this 1
|
||||
add
|
||||
push argument 1
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push this 2
|
||||
push constant 1
|
||||
add
|
||||
pop this 2
|
||||
push pointer 0
|
||||
return
|
||||
function String.eraseLastChar 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 2
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 18
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push this 2
|
||||
push constant 1
|
||||
sub
|
||||
pop this 2
|
||||
push constant 0
|
||||
return
|
||||
function String.intValue 5
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 2
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 0
|
||||
return
|
||||
label IF_FALSE0
|
||||
push constant 0
|
||||
not
|
||||
pop local 3
|
||||
push constant 0
|
||||
push this 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 45
|
||||
eq
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push constant 0
|
||||
not
|
||||
pop local 4
|
||||
push constant 1
|
||||
pop local 0
|
||||
label IF_FALSE1
|
||||
label WHILE_EXP0
|
||||
push local 0
|
||||
push this 2
|
||||
lt
|
||||
push local 3
|
||||
and
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 0
|
||||
push this 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 48
|
||||
sub
|
||||
pop local 2
|
||||
push local 2
|
||||
push constant 0
|
||||
lt
|
||||
push local 2
|
||||
push constant 9
|
||||
gt
|
||||
or
|
||||
not
|
||||
pop local 3
|
||||
push local 3
|
||||
if-goto IF_TRUE2
|
||||
goto IF_FALSE2
|
||||
label IF_TRUE2
|
||||
push local 1
|
||||
push constant 10
|
||||
call Math.multiply 2
|
||||
push local 2
|
||||
add
|
||||
pop local 1
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
label IF_FALSE2
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push local 4
|
||||
if-goto IF_TRUE3
|
||||
goto IF_FALSE3
|
||||
label IF_TRUE3
|
||||
push local 1
|
||||
neg
|
||||
pop local 1
|
||||
label IF_FALSE3
|
||||
push local 1
|
||||
return
|
||||
function String.setInt 4
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 19
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push constant 6
|
||||
call Array.new 1
|
||||
pop local 2
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push constant 0
|
||||
not
|
||||
pop local 3
|
||||
push argument 1
|
||||
neg
|
||||
pop argument 1
|
||||
label IF_FALSE1
|
||||
push argument 1
|
||||
pop local 1
|
||||
label WHILE_EXP0
|
||||
push local 1
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push argument 1
|
||||
push constant 10
|
||||
call Math.divide 2
|
||||
pop local 1
|
||||
push local 0
|
||||
push local 2
|
||||
add
|
||||
push constant 48
|
||||
push argument 1
|
||||
push local 1
|
||||
push constant 10
|
||||
call Math.multiply 2
|
||||
sub
|
||||
add
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
push local 1
|
||||
pop argument 1
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push local 3
|
||||
if-goto IF_TRUE2
|
||||
goto IF_FALSE2
|
||||
label IF_TRUE2
|
||||
push local 0
|
||||
push local 2
|
||||
add
|
||||
push constant 45
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
label IF_FALSE2
|
||||
push this 0
|
||||
push local 0
|
||||
lt
|
||||
if-goto IF_TRUE3
|
||||
goto IF_FALSE3
|
||||
label IF_TRUE3
|
||||
push constant 19
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE3
|
||||
push local 0
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE4
|
||||
goto IF_FALSE4
|
||||
label IF_TRUE4
|
||||
push constant 0
|
||||
push this 1
|
||||
add
|
||||
push constant 48
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push constant 1
|
||||
pop this 2
|
||||
goto IF_END4
|
||||
label IF_FALSE4
|
||||
push constant 0
|
||||
pop this 2
|
||||
label WHILE_EXP1
|
||||
push this 2
|
||||
push local 0
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END1
|
||||
push this 2
|
||||
push this 1
|
||||
add
|
||||
push local 0
|
||||
push this 2
|
||||
push constant 1
|
||||
add
|
||||
sub
|
||||
push local 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push this 2
|
||||
push constant 1
|
||||
add
|
||||
pop this 2
|
||||
goto WHILE_EXP1
|
||||
label WHILE_END1
|
||||
label IF_END4
|
||||
push local 2
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function String.newLine 0
|
||||
push constant 128
|
||||
return
|
||||
function String.backSpace 0
|
||||
push constant 129
|
||||
return
|
||||
function String.doubleQuote 0
|
||||
push constant 34
|
||||
return
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
function Sys.init 0
|
||||
call Memory.init 0
|
||||
pop temp 0
|
||||
call Math.init 0
|
||||
pop temp 0
|
||||
call Screen.init 0
|
||||
pop temp 0
|
||||
call Output.init 0
|
||||
pop temp 0
|
||||
call Keyboard.init 0
|
||||
pop temp 0
|
||||
call Main.main 0
|
||||
pop temp 0
|
||||
call Sys.halt 0
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Sys.halt 0
|
||||
label WHILE_EXP0
|
||||
push constant 0
|
||||
not
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Sys.wait 1
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 1
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
label WHILE_EXP0
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push constant 50
|
||||
pop local 0
|
||||
label WHILE_EXP1
|
||||
push local 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto WHILE_END1
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 0
|
||||
goto WHILE_EXP1
|
||||
label WHILE_END1
|
||||
push argument 0
|
||||
push constant 1
|
||||
sub
|
||||
pop argument 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Sys.error 0
|
||||
push constant 69
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push constant 82
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push constant 82
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push argument 0
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Sys.halt 0
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Memory.jack
|
||||
|
||||
/**
|
||||
* This library provides two services: direct access to the computer's main
|
||||
* memory (RAM), and allocation and recycling of memory blocks. The Hack RAM
|
||||
* consists of 32,768 words, each holding a 16-bit binary number.
|
||||
*/
|
||||
class Memory {
|
||||
static Array mem;
|
||||
/** Initializes the class. */
|
||||
function void init() {
|
||||
let mem = 0;
|
||||
let mem[2048] = 14334;
|
||||
let mem[2049] = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the RAM value at the given address. */
|
||||
function int peek(int address) {
|
||||
return mem[address];
|
||||
}
|
||||
|
||||
/** Sets the RAM value at the given address to the given value. */
|
||||
function void poke(int address, int value) {
|
||||
let mem[address] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Finds an available RAM block of the given size and returns
|
||||
* a reference to its base address. */
|
||||
function int alloc(int size) {
|
||||
var Array current_block;
|
||||
var int tmp;
|
||||
let current_block = 2048;
|
||||
if (size < 0){
|
||||
do Sys.error(5);
|
||||
}
|
||||
if (size = 0){
|
||||
let size = 1;
|
||||
}
|
||||
while (current_block[0] < (size + 2)) {
|
||||
let current_block = current_block[1];
|
||||
}
|
||||
let current_block[0] = current_block[0] - size - 2;
|
||||
let current_block = current_block + current_block[0] + 2;
|
||||
let current_block[0] = size;
|
||||
return current_block + 2;
|
||||
}
|
||||
|
||||
/** De-allocates the given object (cast as an array) by making
|
||||
* it available for future allocations. */
|
||||
function void deAlloc(Array o) {
|
||||
var Array current_block;
|
||||
let current_block = 2048;
|
||||
let o[1]= current_block[1];
|
||||
let current_block[1] = o;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
function Array.new 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 2
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
call Memory.alloc 1
|
||||
return
|
||||
function Array.dispose 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push pointer 0
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+102
@@ -0,0 +1,102 @@
|
||||
function Keyboard.init 0
|
||||
push constant 0
|
||||
return
|
||||
function Keyboard.keyPressed 0
|
||||
push constant 24576
|
||||
call Memory.peek 1
|
||||
return
|
||||
function Keyboard.readChar 2
|
||||
push constant 0
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
label WHILE_EXP0
|
||||
push local 1
|
||||
push constant 0
|
||||
eq
|
||||
push local 0
|
||||
push constant 0
|
||||
gt
|
||||
or
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
call Keyboard.keyPressed 0
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 0
|
||||
gt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push local 0
|
||||
pop local 1
|
||||
label IF_FALSE0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
call String.backSpace 0
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
return
|
||||
function Keyboard.readLine 5
|
||||
push constant 80
|
||||
call String.new 1
|
||||
pop local 3
|
||||
push argument 0
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call String.newLine 0
|
||||
pop local 1
|
||||
call String.backSpace 0
|
||||
pop local 2
|
||||
label WHILE_EXP0
|
||||
push local 4
|
||||
not
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
call Keyboard.readChar 0
|
||||
pop local 0
|
||||
push local 0
|
||||
push local 1
|
||||
eq
|
||||
pop local 4
|
||||
push local 4
|
||||
not
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push local 0
|
||||
push local 2
|
||||
eq
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push local 3
|
||||
call String.eraseLastChar 1
|
||||
pop temp 0
|
||||
goto IF_END1
|
||||
label IF_FALSE1
|
||||
push local 3
|
||||
push local 0
|
||||
call String.appendChar 2
|
||||
pop local 3
|
||||
label IF_END1
|
||||
label IF_FALSE0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push local 3
|
||||
return
|
||||
function Keyboard.readInt 2
|
||||
push argument 0
|
||||
call Keyboard.readLine 1
|
||||
pop local 0
|
||||
push local 0
|
||||
call String.intValue 1
|
||||
pop local 1
|
||||
push local 0
|
||||
call String.dispose 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
return
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/MemoryTest/Main.jack
|
||||
|
||||
/** Test program for the OS Memory class. */
|
||||
class Main {
|
||||
|
||||
/** Performs various memory manipulations. */
|
||||
function void main() {
|
||||
var int temp, err;
|
||||
var Array a, b, c;
|
||||
|
||||
do Memory.poke(8000, 333); // RAM[8000] = 333
|
||||
let temp = Memory.peek(8000);
|
||||
do Memory.poke(8001, temp + 1); // RAM[8001] = 334
|
||||
|
||||
let a = Array.new(3); // uses Memory.alloc
|
||||
let a[2] = 222;
|
||||
do Memory.poke(8002, a[2]); // RAM[8002] = 222
|
||||
|
||||
let err = 0;
|
||||
let b = Array.new(3);
|
||||
let b[1] = a[2] - 100;
|
||||
if (b = a) { // Fail compare if b = a
|
||||
let err = 1; }
|
||||
do Memory.poke(8003, b[1] + err); // RAM[8003] = 122
|
||||
|
||||
let err = 0;
|
||||
let c = Array.new(500);
|
||||
let c[499] = a[2] - b[1];
|
||||
if (c = a) { // Fail compare if c = a
|
||||
let err = 1; }
|
||||
if (c = b) { // Fail compare if c = b
|
||||
let err = err + 10; }
|
||||
do Memory.poke(8004, c[499]+err); // RAM[8004] = 100
|
||||
|
||||
do a.dispose(); // uses Memory.deAlloc
|
||||
do b.dispose();
|
||||
|
||||
let err = 0;
|
||||
let b = Array.new(3);
|
||||
let b[0] = c[499] - 90;
|
||||
if (b = c) { // Fail compare if b = c
|
||||
let err = 1; }
|
||||
do Memory.poke(8005, b[0] + err); // RAM[8005] = 10
|
||||
|
||||
do c.dispose();
|
||||
do b.dispose();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+180
@@ -0,0 +1,180 @@
|
||||
function Main.main 5
|
||||
push constant 8000
|
||||
push constant 333
|
||||
call Memory.poke 2
|
||||
pop temp 0
|
||||
push constant 8000
|
||||
call Memory.peek 1
|
||||
pop local 0
|
||||
push constant 8001
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
call Memory.poke 2
|
||||
pop temp 0
|
||||
push constant 3
|
||||
call Array.new 1
|
||||
pop local 2
|
||||
push local 2
|
||||
push constant 2
|
||||
push constant 222
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 8002
|
||||
push local 2
|
||||
push constant 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
call Memory.poke 2
|
||||
pop temp 0
|
||||
push constant 0
|
||||
pop local 1
|
||||
push constant 3
|
||||
call Array.new 1
|
||||
pop local 3
|
||||
push local 3
|
||||
push constant 1
|
||||
push local 2
|
||||
push constant 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 100
|
||||
sub
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 3
|
||||
push local 2
|
||||
eq
|
||||
not
|
||||
if-goto L0
|
||||
push constant 1
|
||||
pop local 1
|
||||
goto L1
|
||||
label L0
|
||||
label L1
|
||||
push constant 8003
|
||||
push local 3
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 1
|
||||
add
|
||||
call Memory.poke 2
|
||||
pop temp 0
|
||||
push constant 0
|
||||
pop local 1
|
||||
push constant 500
|
||||
call Array.new 1
|
||||
pop local 4
|
||||
push local 4
|
||||
push constant 499
|
||||
push local 2
|
||||
push constant 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 3
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
sub
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push local 2
|
||||
eq
|
||||
not
|
||||
if-goto L2
|
||||
push constant 1
|
||||
pop local 1
|
||||
goto L3
|
||||
label L2
|
||||
label L3
|
||||
push local 4
|
||||
push local 3
|
||||
eq
|
||||
not
|
||||
if-goto L4
|
||||
push local 1
|
||||
push constant 10
|
||||
add
|
||||
pop local 1
|
||||
goto L5
|
||||
label L4
|
||||
label L5
|
||||
push constant 8004
|
||||
push local 4
|
||||
push constant 499
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 1
|
||||
add
|
||||
call Memory.poke 2
|
||||
pop temp 0
|
||||
push local 2
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
push local 3
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
pop local 1
|
||||
push constant 3
|
||||
call Array.new 1
|
||||
pop local 3
|
||||
push local 3
|
||||
push constant 0
|
||||
push local 4
|
||||
push constant 499
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 90
|
||||
sub
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 3
|
||||
push local 4
|
||||
eq
|
||||
not
|
||||
if-goto L6
|
||||
push constant 1
|
||||
pop local 1
|
||||
goto L7
|
||||
label L6
|
||||
label L7
|
||||
push constant 8005
|
||||
push local 3
|
||||
push constant 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 1
|
||||
add
|
||||
call Memory.poke 2
|
||||
pop temp 0
|
||||
push local 4
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
push local 3
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+408
@@ -0,0 +1,408 @@
|
||||
function Math.init 1
|
||||
push constant 16
|
||||
call Array.new 1
|
||||
pop static 1
|
||||
push constant 16
|
||||
call Array.new 1
|
||||
pop static 0
|
||||
push constant 0
|
||||
push static 0
|
||||
add
|
||||
push constant 1
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
label WHILE_EXP0
|
||||
push local 0
|
||||
push constant 15
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
push local 0
|
||||
push static 0
|
||||
add
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Math.abs 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push argument 0
|
||||
neg
|
||||
pop argument 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
return
|
||||
function Math.multiply 5
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 1
|
||||
push constant 0
|
||||
gt
|
||||
and
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
and
|
||||
or
|
||||
pop local 4
|
||||
push argument 0
|
||||
call Math.abs 1
|
||||
pop argument 0
|
||||
push argument 1
|
||||
call Math.abs 1
|
||||
pop argument 1
|
||||
push argument 0
|
||||
push argument 1
|
||||
lt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push argument 0
|
||||
pop local 1
|
||||
push argument 1
|
||||
pop argument 0
|
||||
push local 1
|
||||
pop argument 1
|
||||
label IF_FALSE0
|
||||
label WHILE_EXP0
|
||||
push local 2
|
||||
push constant 1
|
||||
sub
|
||||
push argument 1
|
||||
push constant 1
|
||||
sub
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 3
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 1
|
||||
and
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push local 0
|
||||
push argument 0
|
||||
add
|
||||
pop local 0
|
||||
push local 2
|
||||
push local 3
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop local 2
|
||||
label IF_FALSE1
|
||||
push argument 0
|
||||
push argument 0
|
||||
add
|
||||
pop argument 0
|
||||
push local 3
|
||||
push constant 1
|
||||
add
|
||||
pop local 3
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push local 4
|
||||
if-goto IF_TRUE2
|
||||
goto IF_FALSE2
|
||||
label IF_TRUE2
|
||||
push local 0
|
||||
neg
|
||||
pop local 0
|
||||
label IF_FALSE2
|
||||
push local 0
|
||||
return
|
||||
function Math.divide 4
|
||||
push argument 1
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 3
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 1
|
||||
push constant 0
|
||||
gt
|
||||
and
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
and
|
||||
or
|
||||
pop local 2
|
||||
push constant 0
|
||||
push static 1
|
||||
add
|
||||
push argument 1
|
||||
call Math.abs 1
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push argument 0
|
||||
call Math.abs 1
|
||||
pop argument 0
|
||||
label WHILE_EXP0
|
||||
push local 0
|
||||
push constant 15
|
||||
lt
|
||||
push local 3
|
||||
not
|
||||
and
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push constant 32767
|
||||
push local 0
|
||||
push static 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 1
|
||||
sub
|
||||
sub
|
||||
push local 0
|
||||
push static 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 1
|
||||
sub
|
||||
lt
|
||||
pop local 3
|
||||
push local 3
|
||||
not
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
push static 1
|
||||
add
|
||||
push local 0
|
||||
push static 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 0
|
||||
push static 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
push static 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 1
|
||||
sub
|
||||
push argument 0
|
||||
push constant 1
|
||||
sub
|
||||
gt
|
||||
pop local 3
|
||||
push local 3
|
||||
not
|
||||
if-goto IF_TRUE2
|
||||
goto IF_FALSE2
|
||||
label IF_TRUE2
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
label IF_FALSE2
|
||||
label IF_FALSE1
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
label WHILE_EXP1
|
||||
push local 0
|
||||
push constant 1
|
||||
neg
|
||||
gt
|
||||
not
|
||||
if-goto WHILE_END1
|
||||
push local 0
|
||||
push static 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 1
|
||||
sub
|
||||
push argument 0
|
||||
push constant 1
|
||||
sub
|
||||
gt
|
||||
not
|
||||
if-goto IF_TRUE3
|
||||
goto IF_FALSE3
|
||||
label IF_TRUE3
|
||||
push local 1
|
||||
push local 0
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop local 1
|
||||
push argument 0
|
||||
push local 0
|
||||
push static 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
sub
|
||||
pop argument 0
|
||||
label IF_FALSE3
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 0
|
||||
goto WHILE_EXP1
|
||||
label WHILE_END1
|
||||
push local 2
|
||||
if-goto IF_TRUE4
|
||||
goto IF_FALSE4
|
||||
label IF_TRUE4
|
||||
push local 1
|
||||
neg
|
||||
pop local 1
|
||||
label IF_FALSE4
|
||||
push local 1
|
||||
return
|
||||
function Math.sqrt 4
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 4
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push constant 7
|
||||
pop local 0
|
||||
label WHILE_EXP0
|
||||
push local 0
|
||||
push constant 1
|
||||
neg
|
||||
gt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 3
|
||||
push local 0
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop local 1
|
||||
push local 1
|
||||
push local 1
|
||||
call Math.multiply 2
|
||||
pop local 2
|
||||
push local 2
|
||||
push argument 0
|
||||
gt
|
||||
not
|
||||
push local 2
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
and
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push local 1
|
||||
pop local 3
|
||||
label IF_FALSE1
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push local 3
|
||||
return
|
||||
function Math.max 0
|
||||
push argument 0
|
||||
push argument 1
|
||||
gt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push argument 0
|
||||
pop argument 1
|
||||
label IF_FALSE0
|
||||
push argument 1
|
||||
return
|
||||
function Math.min 0
|
||||
push argument 0
|
||||
push argument 1
|
||||
lt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push argument 0
|
||||
pop argument 1
|
||||
label IF_FALSE0
|
||||
push argument 1
|
||||
return
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Memory.jack
|
||||
|
||||
/**
|
||||
* This library provides two services: direct access to the computer's main
|
||||
* memory (RAM), and allocation and recycling of memory blocks. The Hack RAM
|
||||
* consists of 32,768 words, each holding a 16-bit binary number.
|
||||
*/
|
||||
class Memory {
|
||||
static Array mem;
|
||||
/** Initializes the class. */
|
||||
function void init() {
|
||||
let mem = 0;
|
||||
let mem[2048] = 14334;
|
||||
let mem[2049] = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the RAM value at the given address. */
|
||||
function int peek(int address) {
|
||||
return mem[address];
|
||||
}
|
||||
|
||||
/** Sets the RAM value at the given address to the given value. */
|
||||
function void poke(int address, int value) {
|
||||
let mem[address] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Finds an available RAM block of the given size and returns
|
||||
* a reference to its base address. */
|
||||
function int alloc(int size) {
|
||||
var Array current_block;
|
||||
var int tmp;
|
||||
let current_block = 2048;
|
||||
if (size < 0){
|
||||
do Sys.error(5);
|
||||
}
|
||||
if (size = 0){
|
||||
let size = 1;
|
||||
}
|
||||
while (current_block[0] < (size + 2)) {
|
||||
let current_block = current_block[1];
|
||||
}
|
||||
let current_block[0] = current_block[0] - size - 2;
|
||||
let current_block = current_block + current_block[0] + 2;
|
||||
let current_block[0] = size;
|
||||
return current_block + 2;
|
||||
}
|
||||
|
||||
/** De-allocates the given object (cast as an array) by making
|
||||
* it available for future allocations. */
|
||||
function void deAlloc(Array o) {
|
||||
var Array current_block;
|
||||
let current_block = 2048;
|
||||
let o[1]= current_block[1];
|
||||
let current_block[1] = o;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
Executable
+147
@@ -0,0 +1,147 @@
|
||||
function Memory.init 0
|
||||
push constant 0
|
||||
pop static 0
|
||||
push static 0
|
||||
push constant 2048
|
||||
push constant 14334
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push static 0
|
||||
push constant 2049
|
||||
push constant 1
|
||||
neg
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
function Memory.peek 0
|
||||
push static 0
|
||||
push argument 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
return
|
||||
function Memory.poke 0
|
||||
push static 0
|
||||
push argument 0
|
||||
push argument 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
function Memory.alloc 2
|
||||
push constant 2048
|
||||
pop local 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L0
|
||||
push constant 5
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L1
|
||||
label L0
|
||||
label L1
|
||||
push argument 0
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L2
|
||||
push constant 1
|
||||
pop argument 0
|
||||
goto L3
|
||||
label L2
|
||||
label L3
|
||||
label L4
|
||||
push local 0
|
||||
push constant 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 0
|
||||
push constant 2
|
||||
add
|
||||
lt
|
||||
not
|
||||
if-goto L5
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop local 0
|
||||
goto L4
|
||||
label L5
|
||||
push local 0
|
||||
push constant 0
|
||||
push local 0
|
||||
push constant 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 0
|
||||
sub
|
||||
push constant 2
|
||||
sub
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push local 0
|
||||
push constant 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
push constant 2
|
||||
add
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 0
|
||||
push argument 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 2
|
||||
add
|
||||
return
|
||||
function Memory.deAlloc 1
|
||||
push constant 2048
|
||||
pop local 0
|
||||
push argument 0
|
||||
push constant 1
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
push argument 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+183
@@ -0,0 +1,183 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/MemoryTest/Main.jack
|
||||
|
||||
/** Test program for the OS Memory class. */
|
||||
class Main {
|
||||
|
||||
/** Test Memory.peek(), poke(), alloc() and deAlloc().
|
||||
*
|
||||
* This test is also a diagnostic. RAM[17000] is incremented before and
|
||||
* after every call so that the failure point can be accurately determined
|
||||
* when using command line testing. Return values from all alloc() calls
|
||||
* are also stored in the test results to aid debugging.
|
||||
*/
|
||||
function void main() {
|
||||
var int temp;
|
||||
var Array a, b, c, out;
|
||||
|
||||
let out = 17000; // Address where test results will be stored.
|
||||
|
||||
// Test poke() and peek().
|
||||
|
||||
let out[0] = 10; // poke test
|
||||
do Memory.poke(out + 1, 333); // RAM[17001] = 333
|
||||
|
||||
let out[0] = 11; // peek test
|
||||
let temp = Memory.peek(out + 1);
|
||||
let out[2] = temp + 1; // RAM[17002] = 334
|
||||
let out[0] = 12; // peek/poke test complete
|
||||
|
||||
// Allocate a memory block.
|
||||
// Validate that the returned block is entirely within the heap,
|
||||
// Test aborts if the block is not valid.
|
||||
|
||||
let out[0] = 20;
|
||||
let a = Memory.alloc(20);
|
||||
let out[3] = a; // RAM[17003] = block address
|
||||
|
||||
let out[0] = 21;
|
||||
do Main.checkRange(a, 20);
|
||||
let out[0] = 22;
|
||||
|
||||
// Allocate a SMALLER memory block.
|
||||
// Validate that the returned block is entirely within the heap,
|
||||
// and that it does not overlap block 'a'.
|
||||
// Test aborts if the block is not valid or overlaps.
|
||||
//
|
||||
// Common failure: first block was not removed from free list so space
|
||||
// for this block was found within the first block.
|
||||
|
||||
let out[0] = 30;
|
||||
let b = Memory.alloc(3);
|
||||
let out[4] = b; // RAM[17004] = block address
|
||||
|
||||
let out[0] = 31;
|
||||
do Main.checkRange(b, 3);
|
||||
let out[0] = 32;
|
||||
do Main.checkOverlap(b, 3, a, 3);
|
||||
let out[0] = 33;
|
||||
|
||||
// Allocate a memory block.
|
||||
// Validate that the returned block is entirely within the heap,
|
||||
// and that it does not overlap blocks 'a' or 'b'.
|
||||
// Test aborts if the block is not valid or overlaps.
|
||||
|
||||
let out[0] = 40;
|
||||
let c = Memory.alloc(500);
|
||||
let out[5] = c; // RAM[17005] = block address
|
||||
|
||||
let out[0] = 41;
|
||||
do Main.checkRange(c, 500);
|
||||
let out[0] = 42;
|
||||
do Main.checkOverlap(c, 500, a, 3);
|
||||
let out[0] = 43;
|
||||
do Main.checkOverlap(c, 500, b, 3);
|
||||
let out[0] = 44;
|
||||
|
||||
// Deallocate blocks 'a' and 'b', retaining 'c'.
|
||||
//
|
||||
// Common failure: free list corrupted by deAlloc().
|
||||
|
||||
let out[0] = 50;
|
||||
do Memory.deAlloc(a);
|
||||
|
||||
let out[0] = 51;
|
||||
do Memory.deAlloc(b);
|
||||
let out[0] = 52;
|
||||
|
||||
// Allocate a memory block.
|
||||
// Validate that the returned block is entirely within the heap,
|
||||
// and that it does not overlap blocks 'c'.
|
||||
// Test aborts if the block is not valid or overlaps.
|
||||
//
|
||||
// Common failure: free list corrupted by deAlloc().
|
||||
|
||||
let out[0] = 60;
|
||||
let b = Memory.alloc(3);
|
||||
let out[6] = b; // RAM[17006] = block address
|
||||
|
||||
let out[0] = 61;
|
||||
do Main.checkRange(b, 3);
|
||||
let out[0] = 62;
|
||||
do Main.checkOverlap(b, 3, c, 500);
|
||||
let out[0] = 63;
|
||||
|
||||
// Deallocate blocks 'b' and 'c'.
|
||||
|
||||
let out[0] = 70;
|
||||
do Memory.deAlloc(c);
|
||||
|
||||
let out[0] = 71;
|
||||
do Memory.deAlloc(b);
|
||||
let out[0] = 72;
|
||||
|
||||
// Test that deallocated blocks are placed on the free list and can
|
||||
// be reused.
|
||||
|
||||
let out[0] = 70;
|
||||
let a = Memory.alloc(8000);
|
||||
let out[7] = a; // RAM[17007] = block address
|
||||
|
||||
let out[0] = 71;
|
||||
do Main.checkRange(a, 8000);
|
||||
|
||||
let out[0] = 72;
|
||||
do Memory.deAlloc(a);
|
||||
|
||||
let out[0] = 73;
|
||||
let a = Memory.alloc(7000);
|
||||
|
||||
let out[0] = 74;
|
||||
do Main.checkRange(a, 7000);
|
||||
|
||||
let out[0] = 75;
|
||||
do Memory.deAlloc(a);
|
||||
let out[8] = a; // RAM[17008] = block address
|
||||
|
||||
// Test complete.
|
||||
let out[0] = 100;
|
||||
|
||||
// At this point all allocated blocks have been deallocated.
|
||||
//
|
||||
// You can inspect the free list and confirm that all of the heap is
|
||||
// contained in the free segments.
|
||||
//
|
||||
// If you implemented defragmentation in dealloc(), the free list
|
||||
// should contain only one segment, consisting of the entire heap.
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/** Check that block a(a_len) is in the heap.
|
||||
*
|
||||
* If the block begins or ends outside of the heap, calls Sys.halt()
|
||||
*/
|
||||
function void checkRange(int a, int a_len) {
|
||||
var int a_high;
|
||||
let a_high = (a + a_len)-1;
|
||||
if ((a < 2048) | ((a_high) > 16383)) {
|
||||
// Block is not entirely within heap.
|
||||
do Sys.halt();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Check that block a(a_len) does not overlap block b(b_len).
|
||||
* Assumes that both blocks have been range checked.
|
||||
*
|
||||
* If the blocks overlap, calls Sys.halt()
|
||||
*/
|
||||
function void checkOverlap(int a, int a_len, int b, int b_len) {
|
||||
var int a_high, b_high;
|
||||
let a_high = (a + a_len)-1;
|
||||
let b_high = (b + b_len)-1;
|
||||
if ( ~ ((a > b_high) | (a_high < b))) {
|
||||
// Block overlaps excluded range.
|
||||
do Sys.halt();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+467
@@ -0,0 +1,467 @@
|
||||
function Main.main 5
|
||||
push constant 17000
|
||||
pop local 4
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 10
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 1
|
||||
add
|
||||
push constant 333
|
||||
call Memory.poke 2
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 11
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 1
|
||||
add
|
||||
call Memory.peek 1
|
||||
pop local 0
|
||||
push local 4
|
||||
push constant 2
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 12
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 20
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 20
|
||||
call Memory.alloc 1
|
||||
pop local 1
|
||||
push local 4
|
||||
push constant 3
|
||||
push local 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 21
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 1
|
||||
push constant 20
|
||||
call Main.checkRange 2
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 22
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 30
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 3
|
||||
call Memory.alloc 1
|
||||
pop local 2
|
||||
push local 4
|
||||
push constant 4
|
||||
push local 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 31
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 2
|
||||
push constant 3
|
||||
call Main.checkRange 2
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 32
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 2
|
||||
push constant 3
|
||||
push local 1
|
||||
push constant 3
|
||||
call Main.checkOverlap 4
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 33
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 40
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 500
|
||||
call Memory.alloc 1
|
||||
pop local 3
|
||||
push local 4
|
||||
push constant 5
|
||||
push local 3
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 41
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 3
|
||||
push constant 500
|
||||
call Main.checkRange 2
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 42
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 3
|
||||
push constant 500
|
||||
push local 1
|
||||
push constant 3
|
||||
call Main.checkOverlap 4
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 43
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 3
|
||||
push constant 500
|
||||
push local 2
|
||||
push constant 3
|
||||
call Main.checkOverlap 4
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 44
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 50
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 1
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 51
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 2
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 52
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 60
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 3
|
||||
call Memory.alloc 1
|
||||
pop local 2
|
||||
push local 4
|
||||
push constant 6
|
||||
push local 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 61
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 2
|
||||
push constant 3
|
||||
call Main.checkRange 2
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 62
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 2
|
||||
push constant 3
|
||||
push local 3
|
||||
push constant 500
|
||||
call Main.checkOverlap 4
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 63
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 70
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 3
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 71
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 2
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 72
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 70
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 8000
|
||||
call Memory.alloc 1
|
||||
pop local 1
|
||||
push local 4
|
||||
push constant 7
|
||||
push local 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 71
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 1
|
||||
push constant 8000
|
||||
call Main.checkRange 2
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 72
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 1
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 73
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 7000
|
||||
call Memory.alloc 1
|
||||
pop local 1
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 74
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 1
|
||||
push constant 7000
|
||||
call Main.checkRange 2
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 75
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 1
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 8
|
||||
push local 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 4
|
||||
push constant 0
|
||||
push constant 100
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
function Main.checkRange 1
|
||||
push argument 0
|
||||
push argument 1
|
||||
add
|
||||
push constant 1
|
||||
sub
|
||||
pop local 0
|
||||
push argument 0
|
||||
push constant 2048
|
||||
lt
|
||||
push local 0
|
||||
push constant 16383
|
||||
gt
|
||||
or
|
||||
not
|
||||
if-goto L0
|
||||
call Sys.halt 0
|
||||
pop temp 0
|
||||
goto L1
|
||||
label L0
|
||||
label L1
|
||||
push constant 0
|
||||
return
|
||||
function Main.checkOverlap 2
|
||||
push argument 0
|
||||
push argument 1
|
||||
add
|
||||
push constant 1
|
||||
sub
|
||||
pop local 0
|
||||
push argument 2
|
||||
push argument 3
|
||||
add
|
||||
push constant 1
|
||||
sub
|
||||
pop local 1
|
||||
push argument 0
|
||||
push local 1
|
||||
gt
|
||||
push local 0
|
||||
push argument 2
|
||||
lt
|
||||
or
|
||||
not
|
||||
not
|
||||
if-goto L2
|
||||
call Sys.halt 0
|
||||
pop temp 0
|
||||
goto L3
|
||||
label L2
|
||||
label L3
|
||||
push constant 0
|
||||
return
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008|
|
||||
| 100 | 333 | 334 |*********|*********|*********|*********|*********|*********|
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/MemoryTest/MemoryDiag/MemoryDiag.tst
|
||||
|
||||
echo "At the end of this test it is normal to see some pixels set on the screen";
|
||||
load,
|
||||
output-file MemoryDiag.out,
|
||||
compare-to MemoryDiag.cmp,
|
||||
output-list RAM[17000]%D2.6.1 RAM[17001]%D2.6.1 RAM[17002]%D2.6.1
|
||||
RAM[17003]%D2.6.1 RAM[17004]%D2.6.1 RAM[17005]%D2.6.1 RAM[17006]%D2.6.1
|
||||
RAM[17007]%D2.6.1 RAM[17008]%D2.6.1;
|
||||
|
||||
repeat 1000000 {
|
||||
vmstep;
|
||||
}
|
||||
|
||||
output;
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
<html>
|
||||
<h4>MemoryDiag is both a pass/fail test and a diagnostic.</h4>
|
||||
<p>
|
||||
MemoryDiag tests the following:
|
||||
<ol>
|
||||
<li>Memory.peek() and Memory.poke() read from and write to the specified memory address.</li>
|
||||
<li>Memory.alloc() returns RAM blocks that are fully contained within the heap address range 2048-16383.</li>
|
||||
<li>Memory.alloc() does not return RAM blocks that overlap each other.</li>
|
||||
<li>RAM blocks deallocated by Memory.deAlloc() are made available for Memory.alloc() to reuse.</li>
|
||||
</ol>
|
||||
The block reuse test allocates and deallocates an 8000 word block. It then tries to allocates a 7000 word block which must be allocated from the deallocated 8000 word block. If the 8000 word block is not available for reuse, there will only be about 6300 words available in the heap so you will get an ERR6.
|
||||
<p>
|
||||
<i>At the end of this test it is normal to see some pixels set on the screen.</i> This is because the results of the test are written to RAM[17000] – RAM[17008] which is in the Screen memory. MemoryDiag does not put its results in the first 16K of RAM because it must not interfere with the Memory.jack that is being tested.
|
||||
|
||||
|
||||
<h4>Using MemoryDiag as a diagnostic</h4>
|
||||
|
||||
RAM[17000] is set to a unique value before every system call and address validation. This allows the exact failure location in the test to be identified when automated testing is used. At the end of the test, RAM[17000] is set to 100.
|
||||
<p>
|
||||
When the test fails to compare, look at the MemoryDiag.out file and note the RAM[17000] value. This is the test <i>step</i> that failed. Look through the Main.jack code and find the corresponding<br>
|
||||
  <tt>let out[0] = <i>step</i>;</tt><br>
|
||||
statement. The function immediately following this statement is where the failure occurred.
|
||||
<p>
|
||||
For example, if RAM[17000] is 51, the<br>
|
||||
  <tt>do Memory.deAlloc(b);</tt><br>
|
||||
call did not return. Either there was a simulation error like a bad address or deAlloc() got stuck in a loop.
|
||||
|
||||
|
||||
<h4>Sample MemoryDiag output files</h4>
|
||||
|
||||
<i>Note that RAM[17003] – RAM[17008] are "don't care" values in the MemoryDiag.cmp file.</i>
|
||||
<p>
|
||||
Supplied Memory.vm passes:
|
||||
<pre style="padding-left:2em;">
|
||||
|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008|
|
||||
| 100 | 333 | 334 | 2050 | 2072 | 2077 | 2050 | 2050 | 2050 |
|
||||
</pre>
|
||||
Memory.Jack using the Coursera implementation passes:
|
||||
<pre style="padding-left:2em;">
|
||||
|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008|
|
||||
| 100 | 333 | 334 | 16364 | 16359 | 15857 | 15852 | 7850 | 8850 |
|
||||
</pre>
|
||||
Broken Memory.jack fails (alloc() returns duplicate block address):
|
||||
<pre style="padding-left:2em;">
|
||||
|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008|
|
||||
| 32 | 333 | 334 | 2050 | 2050 | 0 | 0 | 0 | 0 |
|
||||
</pre>
|
||||
Broken Memory.jack fails (deAlloc() does not recycle memory blocks):
|
||||
<pre style="padding-left:2em;">
|
||||
|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008|
|
||||
| 73 | 333 | 334 | 16364 | 16359 | 15857 | 15852 | 7850 | 0 |
|
||||
</pre>
|
||||
|
||||
</html>
|
||||
<p>
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|RAM[8004]|RAM[8005]|
|
||||
| 333 | 334 | 222 | 122 | 100 | 10 |
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|RAM[8004]|RAM[8005]|
|
||||
| 333 | 334 | 222 | 122 | 100 | 10 |
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/MemoryTest/MemoryTest.tst
|
||||
|
||||
load,
|
||||
output-file MemoryTest.out,
|
||||
compare-to MemoryTest.cmp,
|
||||
output-list RAM[8000]%D2.6.1 RAM[8001]%D2.6.1 RAM[8002]%D2.6.1 RAM[8003]%D2.6.1 RAM[8004]%D2.6.1 RAM[8005]%D2.6.1;
|
||||
|
||||
repeat 1000000 {
|
||||
vmstep;
|
||||
}
|
||||
|
||||
output;
|
||||
Executable
+1852
File diff suppressed because it is too large
Load Diff
Executable
+9
@@ -0,0 +1,9 @@
|
||||
There are some specific wrong values that indicate that your Memory.jack
|
||||
returned identical pointers to allocated segments. Look at Main.jack to
|
||||
see where the pointers a, b and c are used.
|
||||
|
||||
RAM[8003] = 123 b = a
|
||||
RAM[8004] = 101 c = a
|
||||
RAM[8004] = 110 c = b
|
||||
RAM[8004] = 111 c = a and c = b
|
||||
RAM[8005] = 11 new b = c
|
||||
Executable
+806
@@ -0,0 +1,806 @@
|
||||
function Screen.init 1
|
||||
push constant 16384
|
||||
pop static 1
|
||||
push constant 0
|
||||
not
|
||||
pop static 2
|
||||
push constant 17
|
||||
call Array.new 1
|
||||
pop static 0
|
||||
push constant 0
|
||||
push static 0
|
||||
add
|
||||
push constant 1
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
label WHILE_EXP0
|
||||
push local 0
|
||||
push constant 16
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
push local 0
|
||||
push static 0
|
||||
add
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.clearScreen 1
|
||||
label WHILE_EXP0
|
||||
push local 0
|
||||
push constant 8192
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 0
|
||||
push static 1
|
||||
add
|
||||
push constant 0
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.updateLocation 0
|
||||
push static 2
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push argument 0
|
||||
push static 1
|
||||
add
|
||||
push argument 0
|
||||
push static 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 1
|
||||
or
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
goto IF_END0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push static 1
|
||||
add
|
||||
push argument 0
|
||||
push static 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 1
|
||||
not
|
||||
and
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
label IF_END0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.setColor 0
|
||||
push argument 0
|
||||
pop static 2
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawPixel 3
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 0
|
||||
push constant 511
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 1
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 7
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push constant 16
|
||||
call Math.divide 2
|
||||
pop local 0
|
||||
push argument 0
|
||||
push local 0
|
||||
push constant 16
|
||||
call Math.multiply 2
|
||||
sub
|
||||
pop local 1
|
||||
push argument 1
|
||||
push constant 32
|
||||
call Math.multiply 2
|
||||
push local 0
|
||||
add
|
||||
pop local 2
|
||||
push local 2
|
||||
push local 1
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawConditional 0
|
||||
push argument 2
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push argument 1
|
||||
push argument 0
|
||||
call Screen.drawPixel 2
|
||||
pop temp 0
|
||||
goto IF_END0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push argument 1
|
||||
call Screen.drawPixel 2
|
||||
pop temp 0
|
||||
label IF_END0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawLine 11
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 2
|
||||
push constant 511
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 3
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 8
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 2
|
||||
push argument 0
|
||||
sub
|
||||
call Math.abs 1
|
||||
pop local 3
|
||||
push argument 3
|
||||
push argument 1
|
||||
sub
|
||||
call Math.abs 1
|
||||
pop local 2
|
||||
push local 3
|
||||
push local 2
|
||||
lt
|
||||
pop local 6
|
||||
push local 6
|
||||
push argument 3
|
||||
push argument 1
|
||||
lt
|
||||
and
|
||||
push local 6
|
||||
not
|
||||
push argument 2
|
||||
push argument 0
|
||||
lt
|
||||
and
|
||||
or
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push argument 0
|
||||
pop local 4
|
||||
push argument 2
|
||||
pop argument 0
|
||||
push local 4
|
||||
pop argument 2
|
||||
push argument 1
|
||||
pop local 4
|
||||
push argument 3
|
||||
pop argument 1
|
||||
push local 4
|
||||
pop argument 3
|
||||
label IF_FALSE1
|
||||
push local 6
|
||||
if-goto IF_TRUE2
|
||||
goto IF_FALSE2
|
||||
label IF_TRUE2
|
||||
push local 3
|
||||
pop local 4
|
||||
push local 2
|
||||
pop local 3
|
||||
push local 4
|
||||
pop local 2
|
||||
push argument 1
|
||||
pop local 1
|
||||
push argument 0
|
||||
pop local 0
|
||||
push argument 3
|
||||
pop local 8
|
||||
push argument 0
|
||||
push argument 2
|
||||
gt
|
||||
pop local 7
|
||||
goto IF_END2
|
||||
label IF_FALSE2
|
||||
push argument 0
|
||||
pop local 1
|
||||
push argument 1
|
||||
pop local 0
|
||||
push argument 2
|
||||
pop local 8
|
||||
push argument 1
|
||||
push argument 3
|
||||
gt
|
||||
pop local 7
|
||||
label IF_END2
|
||||
push constant 2
|
||||
push local 2
|
||||
call Math.multiply 2
|
||||
push local 3
|
||||
sub
|
||||
pop local 5
|
||||
push constant 2
|
||||
push local 2
|
||||
call Math.multiply 2
|
||||
pop local 9
|
||||
push constant 2
|
||||
push local 2
|
||||
push local 3
|
||||
sub
|
||||
call Math.multiply 2
|
||||
pop local 10
|
||||
push local 1
|
||||
push local 0
|
||||
push local 6
|
||||
call Screen.drawConditional 3
|
||||
pop temp 0
|
||||
label WHILE_EXP0
|
||||
push local 1
|
||||
push local 8
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 5
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE3
|
||||
goto IF_FALSE3
|
||||
label IF_TRUE3
|
||||
push local 5
|
||||
push local 9
|
||||
add
|
||||
pop local 5
|
||||
goto IF_END3
|
||||
label IF_FALSE3
|
||||
push local 5
|
||||
push local 10
|
||||
add
|
||||
pop local 5
|
||||
push local 7
|
||||
if-goto IF_TRUE4
|
||||
goto IF_FALSE4
|
||||
label IF_TRUE4
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 0
|
||||
goto IF_END4
|
||||
label IF_FALSE4
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
label IF_END4
|
||||
label IF_END3
|
||||
push local 1
|
||||
push constant 1
|
||||
add
|
||||
pop local 1
|
||||
push local 1
|
||||
push local 0
|
||||
push local 6
|
||||
call Screen.drawConditional 3
|
||||
pop temp 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawRectangle 9
|
||||
push argument 0
|
||||
push argument 2
|
||||
gt
|
||||
push argument 1
|
||||
push argument 3
|
||||
gt
|
||||
or
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 2
|
||||
push constant 511
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 3
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 9
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push constant 16
|
||||
call Math.divide 2
|
||||
pop local 3
|
||||
push argument 0
|
||||
push local 3
|
||||
push constant 16
|
||||
call Math.multiply 2
|
||||
sub
|
||||
pop local 7
|
||||
push argument 2
|
||||
push constant 16
|
||||
call Math.divide 2
|
||||
pop local 4
|
||||
push argument 2
|
||||
push local 4
|
||||
push constant 16
|
||||
call Math.multiply 2
|
||||
sub
|
||||
pop local 8
|
||||
push local 7
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 1
|
||||
sub
|
||||
not
|
||||
pop local 6
|
||||
push local 8
|
||||
push constant 1
|
||||
add
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 5
|
||||
push argument 1
|
||||
push constant 32
|
||||
call Math.multiply 2
|
||||
push local 3
|
||||
add
|
||||
pop local 0
|
||||
push local 4
|
||||
push local 3
|
||||
sub
|
||||
pop local 2
|
||||
label WHILE_EXP0
|
||||
push argument 1
|
||||
push argument 3
|
||||
gt
|
||||
not
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 0
|
||||
push local 2
|
||||
add
|
||||
pop local 1
|
||||
push local 2
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push local 0
|
||||
push local 5
|
||||
push local 6
|
||||
and
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
goto IF_END1
|
||||
label IF_FALSE1
|
||||
push local 0
|
||||
push local 6
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
label WHILE_EXP1
|
||||
push local 0
|
||||
push local 1
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END1
|
||||
push local 0
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
goto WHILE_EXP1
|
||||
label WHILE_END1
|
||||
push local 1
|
||||
push local 5
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
label IF_END1
|
||||
push argument 1
|
||||
push constant 1
|
||||
add
|
||||
pop argument 1
|
||||
push local 1
|
||||
push constant 32
|
||||
add
|
||||
push local 2
|
||||
sub
|
||||
pop local 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawHorizontal 11
|
||||
push argument 1
|
||||
push argument 2
|
||||
call Math.min 2
|
||||
pop local 7
|
||||
push argument 1
|
||||
push argument 2
|
||||
call Math.max 2
|
||||
pop local 8
|
||||
push argument 0
|
||||
push constant 1
|
||||
neg
|
||||
gt
|
||||
push argument 0
|
||||
push constant 256
|
||||
lt
|
||||
and
|
||||
push local 7
|
||||
push constant 512
|
||||
lt
|
||||
and
|
||||
push local 8
|
||||
push constant 1
|
||||
neg
|
||||
gt
|
||||
and
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push local 7
|
||||
push constant 0
|
||||
call Math.max 2
|
||||
pop local 7
|
||||
push local 8
|
||||
push constant 511
|
||||
call Math.min 2
|
||||
pop local 8
|
||||
push local 7
|
||||
push constant 16
|
||||
call Math.divide 2
|
||||
pop local 1
|
||||
push local 7
|
||||
push local 1
|
||||
push constant 16
|
||||
call Math.multiply 2
|
||||
sub
|
||||
pop local 9
|
||||
push local 8
|
||||
push constant 16
|
||||
call Math.divide 2
|
||||
pop local 2
|
||||
push local 8
|
||||
push local 2
|
||||
push constant 16
|
||||
call Math.multiply 2
|
||||
sub
|
||||
pop local 10
|
||||
push local 9
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 1
|
||||
sub
|
||||
not
|
||||
pop local 5
|
||||
push local 10
|
||||
push constant 1
|
||||
add
|
||||
push static 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 4
|
||||
push argument 0
|
||||
push constant 32
|
||||
call Math.multiply 2
|
||||
push local 1
|
||||
add
|
||||
pop local 0
|
||||
push local 2
|
||||
push local 1
|
||||
sub
|
||||
pop local 6
|
||||
push local 0
|
||||
push local 6
|
||||
add
|
||||
pop local 3
|
||||
push local 6
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push local 0
|
||||
push local 4
|
||||
push local 5
|
||||
and
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
goto IF_END1
|
||||
label IF_FALSE1
|
||||
push local 0
|
||||
push local 5
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
label WHILE_EXP0
|
||||
push local 0
|
||||
push local 3
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 0
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push local 3
|
||||
push local 4
|
||||
call Screen.updateLocation 2
|
||||
pop temp 0
|
||||
label IF_END1
|
||||
label IF_FALSE0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawSymetric 0
|
||||
push argument 1
|
||||
push argument 3
|
||||
sub
|
||||
push argument 0
|
||||
push argument 2
|
||||
add
|
||||
push argument 0
|
||||
push argument 2
|
||||
sub
|
||||
call Screen.drawHorizontal 3
|
||||
pop temp 0
|
||||
push argument 1
|
||||
push argument 3
|
||||
add
|
||||
push argument 0
|
||||
push argument 2
|
||||
add
|
||||
push argument 0
|
||||
push argument 2
|
||||
sub
|
||||
call Screen.drawHorizontal 3
|
||||
pop temp 0
|
||||
push argument 1
|
||||
push argument 2
|
||||
sub
|
||||
push argument 0
|
||||
push argument 3
|
||||
sub
|
||||
push argument 0
|
||||
push argument 3
|
||||
add
|
||||
call Screen.drawHorizontal 3
|
||||
pop temp 0
|
||||
push argument 1
|
||||
push argument 2
|
||||
add
|
||||
push argument 0
|
||||
push argument 3
|
||||
sub
|
||||
push argument 0
|
||||
push argument 3
|
||||
add
|
||||
call Screen.drawHorizontal 3
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawCircle 3
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 0
|
||||
push constant 511
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 1
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 12
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push argument 2
|
||||
sub
|
||||
push constant 0
|
||||
lt
|
||||
push argument 0
|
||||
push argument 2
|
||||
add
|
||||
push constant 511
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push argument 2
|
||||
sub
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 1
|
||||
push argument 2
|
||||
add
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push constant 13
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE1
|
||||
push argument 2
|
||||
pop local 1
|
||||
push constant 1
|
||||
push argument 2
|
||||
sub
|
||||
pop local 2
|
||||
push argument 0
|
||||
push argument 1
|
||||
push local 0
|
||||
push local 1
|
||||
call Screen.drawSymetric 4
|
||||
pop temp 0
|
||||
label WHILE_EXP0
|
||||
push local 1
|
||||
push local 0
|
||||
gt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 2
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE2
|
||||
goto IF_FALSE2
|
||||
label IF_TRUE2
|
||||
push local 2
|
||||
push constant 2
|
||||
push local 0
|
||||
call Math.multiply 2
|
||||
add
|
||||
push constant 3
|
||||
add
|
||||
pop local 2
|
||||
goto IF_END2
|
||||
label IF_FALSE2
|
||||
push local 2
|
||||
push constant 2
|
||||
push local 0
|
||||
push local 1
|
||||
sub
|
||||
call Math.multiply 2
|
||||
add
|
||||
push constant 5
|
||||
add
|
||||
pop local 2
|
||||
push local 1
|
||||
push constant 1
|
||||
sub
|
||||
pop local 1
|
||||
label IF_END2
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
push argument 0
|
||||
push argument 1
|
||||
push local 0
|
||||
push local 1
|
||||
call Screen.drawSymetric 4
|
||||
pop temp 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+393
@@ -0,0 +1,393 @@
|
||||
function String.new 0
|
||||
push constant 3
|
||||
call Memory.alloc 1
|
||||
pop pointer 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 14
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push argument 0
|
||||
call Array.new 1
|
||||
pop this 1
|
||||
label IF_FALSE1
|
||||
push argument 0
|
||||
pop this 0
|
||||
push constant 0
|
||||
pop this 2
|
||||
push pointer 0
|
||||
return
|
||||
function String.dispose 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
push constant 0
|
||||
gt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push this 1
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push pointer 0
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function String.length 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 2
|
||||
return
|
||||
function String.charAt 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
push argument 1
|
||||
push this 2
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push this 2
|
||||
eq
|
||||
or
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 15
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 1
|
||||
push this 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
return
|
||||
function String.setCharAt 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
push argument 1
|
||||
push this 2
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push this 2
|
||||
eq
|
||||
or
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 16
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push argument 1
|
||||
push this 1
|
||||
add
|
||||
push argument 2
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
function String.appendChar 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 2
|
||||
push this 0
|
||||
eq
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 17
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push this 2
|
||||
push this 1
|
||||
add
|
||||
push argument 1
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push this 2
|
||||
push constant 1
|
||||
add
|
||||
pop this 2
|
||||
push pointer 0
|
||||
return
|
||||
function String.eraseLastChar 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 2
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 18
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push this 2
|
||||
push constant 1
|
||||
sub
|
||||
pop this 2
|
||||
push constant 0
|
||||
return
|
||||
function String.intValue 5
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 2
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 0
|
||||
return
|
||||
label IF_FALSE0
|
||||
push constant 0
|
||||
not
|
||||
pop local 3
|
||||
push constant 0
|
||||
push this 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 45
|
||||
eq
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push constant 0
|
||||
not
|
||||
pop local 4
|
||||
push constant 1
|
||||
pop local 0
|
||||
label IF_FALSE1
|
||||
label WHILE_EXP0
|
||||
push local 0
|
||||
push this 2
|
||||
lt
|
||||
push local 3
|
||||
and
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push local 0
|
||||
push this 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 48
|
||||
sub
|
||||
pop local 2
|
||||
push local 2
|
||||
push constant 0
|
||||
lt
|
||||
push local 2
|
||||
push constant 9
|
||||
gt
|
||||
or
|
||||
not
|
||||
pop local 3
|
||||
push local 3
|
||||
if-goto IF_TRUE2
|
||||
goto IF_FALSE2
|
||||
label IF_TRUE2
|
||||
push local 1
|
||||
push constant 10
|
||||
call Math.multiply 2
|
||||
push local 2
|
||||
add
|
||||
pop local 1
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
label IF_FALSE2
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push local 4
|
||||
if-goto IF_TRUE3
|
||||
goto IF_FALSE3
|
||||
label IF_TRUE3
|
||||
push local 1
|
||||
neg
|
||||
pop local 1
|
||||
label IF_FALSE3
|
||||
push local 1
|
||||
return
|
||||
function String.setInt 4
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 19
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
push constant 6
|
||||
call Array.new 1
|
||||
pop local 2
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE1
|
||||
goto IF_FALSE1
|
||||
label IF_TRUE1
|
||||
push constant 0
|
||||
not
|
||||
pop local 3
|
||||
push argument 1
|
||||
neg
|
||||
pop argument 1
|
||||
label IF_FALSE1
|
||||
push argument 1
|
||||
pop local 1
|
||||
label WHILE_EXP0
|
||||
push local 1
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push argument 1
|
||||
push constant 10
|
||||
call Math.divide 2
|
||||
pop local 1
|
||||
push local 0
|
||||
push local 2
|
||||
add
|
||||
push constant 48
|
||||
push argument 1
|
||||
push local 1
|
||||
push constant 10
|
||||
call Math.multiply 2
|
||||
sub
|
||||
add
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
push local 1
|
||||
pop argument 1
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push local 3
|
||||
if-goto IF_TRUE2
|
||||
goto IF_FALSE2
|
||||
label IF_TRUE2
|
||||
push local 0
|
||||
push local 2
|
||||
add
|
||||
push constant 45
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
label IF_FALSE2
|
||||
push this 0
|
||||
push local 0
|
||||
lt
|
||||
if-goto IF_TRUE3
|
||||
goto IF_FALSE3
|
||||
label IF_TRUE3
|
||||
push constant 19
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE3
|
||||
push local 0
|
||||
push constant 0
|
||||
eq
|
||||
if-goto IF_TRUE4
|
||||
goto IF_FALSE4
|
||||
label IF_TRUE4
|
||||
push constant 0
|
||||
push this 1
|
||||
add
|
||||
push constant 48
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push constant 1
|
||||
pop this 2
|
||||
goto IF_END4
|
||||
label IF_FALSE4
|
||||
push constant 0
|
||||
pop this 2
|
||||
label WHILE_EXP1
|
||||
push this 2
|
||||
push local 0
|
||||
lt
|
||||
not
|
||||
if-goto WHILE_END1
|
||||
push this 2
|
||||
push this 1
|
||||
add
|
||||
push local 0
|
||||
push this 2
|
||||
push constant 1
|
||||
add
|
||||
sub
|
||||
push local 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop temp 0
|
||||
pop pointer 1
|
||||
push temp 0
|
||||
pop that 0
|
||||
push this 2
|
||||
push constant 1
|
||||
add
|
||||
pop this 2
|
||||
goto WHILE_EXP1
|
||||
label WHILE_END1
|
||||
label IF_END4
|
||||
push local 2
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function String.newLine 0
|
||||
push constant 128
|
||||
return
|
||||
function String.backSpace 0
|
||||
push constant 129
|
||||
return
|
||||
function String.doubleQuote 0
|
||||
push constant 34
|
||||
return
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
function Sys.init 0
|
||||
call Memory.init 0
|
||||
pop temp 0
|
||||
call Math.init 0
|
||||
pop temp 0
|
||||
call Screen.init 0
|
||||
pop temp 0
|
||||
call Output.init 0
|
||||
pop temp 0
|
||||
call Keyboard.init 0
|
||||
pop temp 0
|
||||
call Main.main 0
|
||||
pop temp 0
|
||||
call Sys.halt 0
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Sys.halt 0
|
||||
label WHILE_EXP0
|
||||
push constant 0
|
||||
not
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Sys.wait 1
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
if-goto IF_TRUE0
|
||||
goto IF_FALSE0
|
||||
label IF_TRUE0
|
||||
push constant 1
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
label IF_FALSE0
|
||||
label WHILE_EXP0
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto WHILE_END0
|
||||
push constant 50
|
||||
pop local 0
|
||||
label WHILE_EXP1
|
||||
push local 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto WHILE_END1
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 0
|
||||
goto WHILE_EXP1
|
||||
label WHILE_END1
|
||||
push argument 0
|
||||
push constant 1
|
||||
sub
|
||||
pop argument 0
|
||||
goto WHILE_EXP0
|
||||
label WHILE_END0
|
||||
push constant 0
|
||||
return
|
||||
function Sys.error 0
|
||||
push constant 69
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push constant 82
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push constant 82
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push argument 0
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Sys.halt 0
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
+301
@@ -0,0 +1,301 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Output.jack
|
||||
|
||||
/**
|
||||
* A library of functions for writing text on the screen.
|
||||
* The Hack physical screen consists of 512 rows of 256 pixels each.
|
||||
* The library uses a fixed font, in which each character is displayed
|
||||
* within a frame which is 11 pixels high (including 1 pixel for inter-line
|
||||
* spacing) and 8 pixels wide (including 2 pixels for inter-character spacing).
|
||||
* The resulting grid accommodates 23 rows (indexed 0..22, top to bottom)
|
||||
* of 64 characters each (indexed 0..63, left to right). The top left
|
||||
* character position on the screen is indexed (0,0). A cursor, implemented
|
||||
* as a small filled square, indicates where the next character will be displayed.
|
||||
*/
|
||||
class Output {
|
||||
|
||||
// Character map for displaying characters
|
||||
static Array charMaps;
|
||||
static int address;
|
||||
static bool half;
|
||||
|
||||
/** Initializes the screen, and locates the cursor at the screen's top-left. */
|
||||
function void init() {
|
||||
do Output.initMap();
|
||||
do Output.moveCursor(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Initializes the character map array
|
||||
function void initMap() {
|
||||
var int i;
|
||||
|
||||
let charMaps = Array.new(127);
|
||||
|
||||
// Black square, used for displaying non-printable characters.
|
||||
do Output.create(0,63,63,63,63,63,63,63,63,63,0,0);
|
||||
|
||||
// Assigns the bitmap for each character in the charachter set.
|
||||
// The first parameter is the character index, the next 11 numbers
|
||||
// are the values of each row in the frame that represents this character.
|
||||
do Output.create(32,0,0,0,0,0,0,0,0,0,0,0); //
|
||||
do Output.create(33,12,30,30,30,12,12,0,12,12,0,0); // !
|
||||
do Output.create(34,54,54,20,0,0,0,0,0,0,0,0); // "
|
||||
do Output.create(35,0,18,18,63,18,18,63,18,18,0,0); // #
|
||||
do Output.create(36,12,30,51,3,30,48,51,30,12,12,0); // $
|
||||
do Output.create(37,0,0,35,51,24,12,6,51,49,0,0); // %
|
||||
do Output.create(38,12,30,30,12,54,27,27,27,54,0,0); // &
|
||||
do Output.create(39,12,12,6,0,0,0,0,0,0,0,0); // '
|
||||
do Output.create(40,24,12,6,6,6,6,6,12,24,0,0); // (
|
||||
do Output.create(41,6,12,24,24,24,24,24,12,6,0,0); // )
|
||||
do Output.create(42,0,0,0,51,30,63,30,51,0,0,0); // *
|
||||
do Output.create(43,0,0,0,12,12,63,12,12,0,0,0); // +
|
||||
do Output.create(44,0,0,0,0,0,0,0,12,12,6,0); // ,
|
||||
do Output.create(45,0,0,0,0,0,63,0,0,0,0,0); // -
|
||||
do Output.create(46,0,0,0,0,0,0,0,12,12,0,0); // .
|
||||
do Output.create(47,0,0,32,48,24,12,6,3,1,0,0); // /
|
||||
|
||||
do Output.create(48,12,30,51,51,51,51,51,30,12,0,0); // 0
|
||||
do Output.create(49,12,14,15,12,12,12,12,12,63,0,0); // 1
|
||||
do Output.create(50,30,51,48,24,12,6,3,51,63,0,0); // 2
|
||||
do Output.create(51,30,51,48,48,28,48,48,51,30,0,0); // 3
|
||||
do Output.create(52,16,24,28,26,25,63,24,24,60,0,0); // 4
|
||||
do Output.create(53,63,3,3,31,48,48,48,51,30,0,0); // 5
|
||||
do Output.create(54,28,6,3,3,31,51,51,51,30,0,0); // 6
|
||||
do Output.create(55,63,49,48,48,24,12,12,12,12,0,0); // 7
|
||||
do Output.create(56,30,51,51,51,30,51,51,51,30,0,0); // 8
|
||||
do Output.create(57,30,51,51,51,62,48,48,24,14,0,0); // 9
|
||||
|
||||
do Output.create(58,0,0,12,12,0,0,12,12,0,0,0); // :
|
||||
do Output.create(59,0,0,12,12,0,0,12,12,6,0,0); // ;
|
||||
do Output.create(60,0,0,24,12,6,3,6,12,24,0,0); // <
|
||||
do Output.create(61,0,0,0,63,0,0,63,0,0,0,0); // =
|
||||
do Output.create(62,0,0,3,6,12,24,12,6,3,0,0); // >
|
||||
do Output.create(64,30,51,51,59,59,59,27,3,30,0,0); // @
|
||||
do Output.create(63,30,51,51,24,12,12,0,12,12,0,0); // ?
|
||||
|
||||
do Output.create(65,12,30,51,51,63,51,51,51,51,0,0); // A ** TO BE FILLED **
|
||||
do Output.create(66,31,51,51,51,31,51,51,51,31,0,0); // B
|
||||
do Output.create(67,28,54,35,3,3,3,35,54,28,0,0); // C
|
||||
do Output.create(68,15,27,51,51,51,51,51,27,15,0,0); // D
|
||||
do Output.create(69,63,51,35,11,15,11,35,51,63,0,0); // E
|
||||
do Output.create(70,63,51,35,11,15,11,3,3,3,0,0); // F
|
||||
do Output.create(71,28,54,35,3,59,51,51,54,44,0,0); // G
|
||||
do Output.create(72,51,51,51,51,63,51,51,51,51,0,0); // H
|
||||
do Output.create(73,30,12,12,12,12,12,12,12,30,0,0); // I
|
||||
do Output.create(74,60,24,24,24,24,24,27,27,14,0,0); // J
|
||||
do Output.create(75,51,51,51,27,15,27,51,51,51,0,0); // K
|
||||
do Output.create(76,3,3,3,3,3,3,35,51,63,0,0); // L
|
||||
do Output.create(77,33,51,63,63,51,51,51,51,51,0,0); // M
|
||||
do Output.create(78,51,51,55,55,63,59,59,51,51,0,0); // N
|
||||
do Output.create(79,30,51,51,51,51,51,51,51,30,0,0); // O
|
||||
do Output.create(80,31,51,51,51,31,3,3,3,3,0,0); // P
|
||||
do Output.create(81,30,51,51,51,51,51,63,59,30,48,0);// Q
|
||||
do Output.create(82,31,51,51,51,31,27,51,51,51,0,0); // R
|
||||
do Output.create(83,30,51,51,6,28,48,51,51,30,0,0); // S
|
||||
do Output.create(84,63,63,45,12,12,12,12,12,30,0,0); // T
|
||||
do Output.create(85,51,51,51,51,51,51,51,51,30,0,0); // U
|
||||
do Output.create(86,51,51,51,51,51,30,30,12,12,0,0); // V
|
||||
do Output.create(87,51,51,51,51,51,63,63,63,18,0,0); // W
|
||||
do Output.create(88,51,51,30,30,12,30,30,51,51,0,0); // X
|
||||
do Output.create(89,51,51,51,51,30,12,12,12,30,0,0); // Y
|
||||
do Output.create(90,63,51,49,24,12,6,35,51,63,0,0); // Z
|
||||
|
||||
do Output.create(91,30,6,6,6,6,6,6,6,30,0,0); // [
|
||||
do Output.create(92,0,0,1,3,6,12,24,48,32,0,0); // \
|
||||
do Output.create(93,30,24,24,24,24,24,24,24,30,0,0); // ]
|
||||
do Output.create(94,8,28,54,0,0,0,0,0,0,0,0); // ^
|
||||
do Output.create(95,0,0,0,0,0,0,0,0,0,63,0); // _
|
||||
do Output.create(96,6,12,24,0,0,0,0,0,0,0,0); // `
|
||||
|
||||
do Output.create(97,0,0,0,14,24,30,27,27,54,0,0); // a
|
||||
do Output.create(98,3,3,3,15,27,51,51,51,30,0,0); // b
|
||||
do Output.create(99,0,0,0,30,51,3,3,51,30,0,0); // c
|
||||
do Output.create(100,48,48,48,60,54,51,51,51,30,0,0); // d
|
||||
do Output.create(101,0,0,0,30,51,63,3,51,30,0,0); // e
|
||||
do Output.create(102,28,54,38,6,15,6,6,6,15,0,0); // f
|
||||
do Output.create(103,0,0,30,51,51,51,62,48,51,30,0); // g
|
||||
do Output.create(104,3,3,3,27,55,51,51,51,51,0,0); // h
|
||||
do Output.create(105,12,12,0,14,12,12,12,12,30,0,0); // i
|
||||
do Output.create(106,48,48,0,56,48,48,48,48,51,30,0); // j
|
||||
do Output.create(107,3,3,3,51,27,15,15,27,51,0,0); // k
|
||||
do Output.create(108,14,12,12,12,12,12,12,12,30,0,0); // l
|
||||
do Output.create(109,0,0,0,29,63,43,43,43,43,0,0); // m
|
||||
do Output.create(110,0,0,0,29,51,51,51,51,51,0,0); // n
|
||||
do Output.create(111,0,0,0,30,51,51,51,51,30,0,0); // o
|
||||
do Output.create(112,0,0,0,30,51,51,51,31,3,3,0); // p
|
||||
do Output.create(113,0,0,0,30,51,51,51,62,48,48,0); // q
|
||||
do Output.create(114,0,0,0,29,55,51,3,3,7,0,0); // r
|
||||
do Output.create(115,0,0,0,30,51,6,24,51,30,0,0); // s
|
||||
do Output.create(116,4,6,6,15,6,6,6,54,28,0,0); // t
|
||||
do Output.create(117,0,0,0,27,27,27,27,27,54,0,0); // u
|
||||
do Output.create(118,0,0,0,51,51,51,51,30,12,0,0); // v
|
||||
do Output.create(119,0,0,0,51,51,51,63,63,18,0,0); // w
|
||||
do Output.create(120,0,0,0,51,30,12,12,30,51,0,0); // x
|
||||
do Output.create(121,0,0,0,51,51,51,62,48,24,15,0); // y
|
||||
do Output.create(122,0,0,0,63,27,12,6,51,63,0,0); // z
|
||||
|
||||
do Output.create(123,56,12,12,12,7,12,12,12,56,0,0); // {
|
||||
do Output.create(124,12,12,12,12,12,12,12,12,12,0,0); // |
|
||||
do Output.create(125,7,12,12,12,56,12,12,12,7,0,0); // }
|
||||
do Output.create(126,38,45,25,0,0,0,0,0,0,0,0); // ~
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Creates the character map array of the given character index, using the given values.
|
||||
function void create(int index, int a, int b, int c, int d, int e,
|
||||
int f, int g, int h, int i, int j, int k) {
|
||||
var Array map;
|
||||
|
||||
let map = Array.new(11);
|
||||
let charMaps[index] = map;
|
||||
|
||||
let map[0] = a;
|
||||
let map[1] = b;
|
||||
let map[2] = c;
|
||||
let map[3] = d;
|
||||
let map[4] = e;
|
||||
let map[5] = f;
|
||||
let map[6] = g;
|
||||
let map[7] = h;
|
||||
let map[8] = i;
|
||||
let map[9] = j;
|
||||
let map[10] = k;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Returns the character map (array of size 11) of the given character.
|
||||
// If the given character is invalid or non-printable, returns the
|
||||
// character map of a black square.
|
||||
function Array getMap(char c) {
|
||||
if ((c < 32) | (c > 126)) {
|
||||
let c = 0;
|
||||
}
|
||||
return charMaps[c];
|
||||
}
|
||||
|
||||
/** Moves the cursor to the j-th column of the i-th row,
|
||||
* and erases the character displayed there. */
|
||||
function void moveCursor(int i, int j) {
|
||||
var int count;
|
||||
var int display;
|
||||
var Array r;
|
||||
var Array char;
|
||||
if (j = 0){
|
||||
let half = true;
|
||||
}
|
||||
else{
|
||||
let half = (j / 2) * 2 = j; // chetno true, 1vaa chast
|
||||
}
|
||||
let address = (352 * i) + (j / 2) + 16384;
|
||||
let char = Output.getMap(32);
|
||||
|
||||
while (count < 11){
|
||||
if (half){
|
||||
let display = r[address] & (-256);
|
||||
let r[address] = char[count] | display;
|
||||
}
|
||||
else{
|
||||
let display = r[address] & 255;
|
||||
let r[address] = (char[count]*256) | display;
|
||||
}
|
||||
let count = count + 1;
|
||||
let address = address + 32;
|
||||
}
|
||||
let address = address - 352;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given character at the cursor location,
|
||||
* and advances the cursor one column forward. */
|
||||
function void printChar(char c) {
|
||||
var Array char;
|
||||
var Array r;
|
||||
var int count;
|
||||
var int display;
|
||||
let char = Output.getMap(c);
|
||||
while (count < 11){
|
||||
if (half){
|
||||
let display = r[address] & (-256);
|
||||
let r[address] = char[count] | display;
|
||||
}
|
||||
else{
|
||||
let display = r[address] & 255;
|
||||
let r[address] = (char[count]*256) | display;
|
||||
}
|
||||
let count = count + 1;
|
||||
let address = address + 32;
|
||||
}
|
||||
|
||||
if (half){
|
||||
let address = address - 352;
|
||||
let half = false;
|
||||
}
|
||||
else{
|
||||
if (address > 24480){
|
||||
let address = 16384;
|
||||
let half = true;
|
||||
}
|
||||
else{
|
||||
let address = address - 351;
|
||||
let half = true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** displays the given string starting at the cursor location,
|
||||
* and advances the cursor appropriately. */
|
||||
function void printString(String s) {
|
||||
var int i, length;
|
||||
let length = s.length();
|
||||
while (i < length){
|
||||
do Output.printChar(s[i+2]);
|
||||
let i = i + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given integer starting at the cursor location,
|
||||
* and advances the cursor appropriately. */
|
||||
function void printInt(int i) {
|
||||
var String s;
|
||||
let s = String.new(6);
|
||||
do s.setInt(i);
|
||||
do Output.printString(s);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Advances the cursor to the beginning of the next line. */
|
||||
function void println() {
|
||||
var int row;
|
||||
let row = (((address - 16384) / 32)/11) + 1;
|
||||
if (row > 32){
|
||||
let row = 0;
|
||||
}
|
||||
do Output.moveCursor(row, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the cursor one column back. */
|
||||
function void backSpace() {
|
||||
if (address = 16384){
|
||||
let address = 24191;
|
||||
let half = true;
|
||||
return;
|
||||
}
|
||||
if (half){
|
||||
|
||||
let address = address - 1;
|
||||
let half = false;
|
||||
}
|
||||
else{
|
||||
let half = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/OutputTest/Main.jack
|
||||
|
||||
/** Test program for the OS Output class. */
|
||||
class Main {
|
||||
|
||||
/** Outputs the entire character set to the screen using all the
|
||||
* methods of the Output class. */
|
||||
function void main() {
|
||||
var String s;
|
||||
|
||||
let s = String.new(1);
|
||||
do s.appendChar(String.doubleQuote());
|
||||
|
||||
do Output.moveCursor(0, 63);
|
||||
do Output.printChar(66);
|
||||
do Output.moveCursor(22, 0);
|
||||
do Output.printChar(67);
|
||||
do Output.moveCursor(22, 63);
|
||||
do Output.printChar(68);
|
||||
do Output.printChar(65);
|
||||
|
||||
do Output.moveCursor(2, 0);
|
||||
do Output.printString("0123456789");
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz");
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("!#$%&'()*+,-./:;<=>?@[\]^_`{|}~");
|
||||
do Output.printString(s);
|
||||
do Output.println();
|
||||
|
||||
do Output.printInt(-12345);
|
||||
do Output.backSpace();
|
||||
do Output.printInt(6789);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
+206
@@ -0,0 +1,206 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Screen.jack
|
||||
|
||||
/**
|
||||
* A library of functions for displaying graphics on the screen.
|
||||
* The Hack physical screen consists of 256 rows (indexed 0..255, top to bottom)
|
||||
* of 512 pixels each (indexed 0..511, left to right). The top left pixel on
|
||||
* the screen is indexed (0,0).
|
||||
*/
|
||||
class Screen {
|
||||
|
||||
static Array mem;
|
||||
static Array st;
|
||||
static boolean color;
|
||||
/** Initializes the Screen. */
|
||||
function void init() {
|
||||
var int a;
|
||||
let st = Array.new(16);
|
||||
let st[0] = 1;
|
||||
while (a < 15){
|
||||
let a = a + 1;
|
||||
let st[a] = st[a - 1] + st[a - 1];
|
||||
}
|
||||
let color = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Erases the entire screen. */
|
||||
function void clearScreen() {
|
||||
var int a;
|
||||
let a = 16384;
|
||||
while (a < 24575){
|
||||
let mem[a] = 0;
|
||||
let a = a + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Sets the current color, to be used for all subsequent drawXXX commands.
|
||||
* Black is represented by true, white by false. */
|
||||
function void setColor(boolean b) {
|
||||
let color = b;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws the (x,y) pixel, using the current color. */
|
||||
function void drawPixel(int x, int y) {
|
||||
var int value, address, bit, mem_block;
|
||||
if ((x > 511) | (x < 0) | (y > 255) | (y < 0)){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let mem_block = x / 16;
|
||||
let address = (32 * y) + mem_block + 16384;
|
||||
let value = mem[address];
|
||||
let bit = x - (mem_block * 16);
|
||||
if (color){
|
||||
let mem[address] = st[bit] | value;
|
||||
}
|
||||
else{
|
||||
let mem[address] = (~st[bit])& value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws a line from pixel (x1,y1) to pixel (x2,y2), using the current color. */
|
||||
function void drawLine(int x1, int y1, int x2, int y2) {
|
||||
var int diff, dx, dy, a, b;
|
||||
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
|
||||
do Sys.error(8);
|
||||
}
|
||||
let dx = x2 - x1;
|
||||
let dy = y2 - y1;
|
||||
if (dx = 0){
|
||||
if (dy > 0){
|
||||
while(~(b > dy)){
|
||||
do Screen.drawPixel(x1, y1 + b);
|
||||
let b = b + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else{
|
||||
while(~(b < dy)){
|
||||
do Screen.drawPixel(x1, y1 + b);
|
||||
let b = b - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dy = 0){
|
||||
if (dx > 0){
|
||||
while(~(a > dx)){
|
||||
do Screen.drawPixel(x1 + a, y1);
|
||||
let a = a + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else{
|
||||
while(~(a < dx)){
|
||||
do Screen.drawPixel(x1 + a, y1);
|
||||
let a = a - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dx < 0){
|
||||
if (dy < 0){
|
||||
while ((~(a < dx)) & (~(b < dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a - 1;
|
||||
let diff = diff - dy;
|
||||
}
|
||||
else{
|
||||
let b = b - 1;
|
||||
let diff = diff + dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
while ((~(a < dx)) & (~(b > dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a - 1;
|
||||
let diff = diff + dy;
|
||||
}
|
||||
else{
|
||||
let b = b + 1;
|
||||
let diff = diff + dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (dy < 0){
|
||||
while ((~(a > dx)) & (~(b < dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a + 1;
|
||||
let diff = diff - dy;
|
||||
}
|
||||
else{
|
||||
let b = b - 1;
|
||||
let diff = diff - dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
while ((~(a > dx)) & (~(b > dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a + 1;
|
||||
let diff = diff + dy;
|
||||
}
|
||||
else{
|
||||
let b = b + 1;
|
||||
let diff = diff - dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws a filled rectangle whose top left corner is (x1, y1)
|
||||
* and bottom right corner is (x2,y2), using the current color. */
|
||||
function void drawRectangle(int x1, int y1, int x2, int y2) {
|
||||
var int a, tmp;
|
||||
if (x1 > x2){
|
||||
let tmp = x1;
|
||||
let x1 = x2;
|
||||
let x2 = tmp;
|
||||
}
|
||||
if (y1 > y2){
|
||||
let tmp = y1;
|
||||
let y1 = y2;
|
||||
let y2 = tmp;
|
||||
}
|
||||
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
|
||||
do Sys.error(8);
|
||||
}
|
||||
let tmp = y2 - y1;
|
||||
while(a < tmp){
|
||||
do Screen.drawLine(x1, y1 + a, x2, y1 + a);
|
||||
let a = a + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws a filled circle of radius r<=181 around (x,y), using the current color. */
|
||||
function void drawCircle(int x, int y, int r) {
|
||||
var int dy, dx, tmp;
|
||||
if(r > 181){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let dy = - r;
|
||||
while (dy < r){
|
||||
let tmp = Math.sqrt((r * r) - (dy * dy));
|
||||
do Screen.drawLine(x - tmp, y + dy, x + tmp, y + dy);
|
||||
let dy = dy + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/ScreenTest/Main.jack
|
||||
|
||||
/** Test program for the OS Screen class. */
|
||||
class Main {
|
||||
|
||||
/** Draws a sample pictue on the screen using lines and circles. */
|
||||
function void main() {
|
||||
|
||||
do Screen.drawLine(0,220,511,220); // base line
|
||||
do Screen.drawRectangle(280,90,410,220); // house
|
||||
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(350,120,390,219); // door
|
||||
do Screen.drawRectangle(292,120,332,150); // window
|
||||
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawCircle(360,170,3); // door handle
|
||||
do Screen.drawLine(280,90,345,35); // roof
|
||||
do Screen.drawLine(345,35,410,90); // roof
|
||||
|
||||
do Screen.drawCircle(140,60,30); // sun
|
||||
do Screen.drawLine(140,26, 140, 6);
|
||||
do Screen.drawLine(163,35,178,20);
|
||||
do Screen.drawLine(174,60,194,60);
|
||||
do Screen.drawLine(163,85,178,100);
|
||||
do Screen.drawLine(140,94,140,114);
|
||||
do Screen.drawLine(117,85,102,100);
|
||||
do Screen.drawLine(106,60,86,60);
|
||||
do Screen.drawLine(117,35,102,20);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+104
@@ -0,0 +1,104 @@
|
||||
function Main.main 0
|
||||
push constant 0
|
||||
push constant 220
|
||||
push constant 511
|
||||
push constant 220
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push constant 280
|
||||
push constant 90
|
||||
push constant 410
|
||||
push constant 220
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push constant 0
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push constant 350
|
||||
push constant 120
|
||||
push constant 390
|
||||
push constant 219
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push constant 292
|
||||
push constant 120
|
||||
push constant 332
|
||||
push constant 150
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push constant 360
|
||||
push constant 170
|
||||
push constant 3
|
||||
call Screen.drawCircle 3
|
||||
pop temp 0
|
||||
push constant 280
|
||||
push constant 90
|
||||
push constant 345
|
||||
push constant 35
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push constant 345
|
||||
push constant 35
|
||||
push constant 410
|
||||
push constant 90
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push constant 140
|
||||
push constant 60
|
||||
push constant 30
|
||||
call Screen.drawCircle 3
|
||||
pop temp 0
|
||||
push constant 140
|
||||
push constant 26
|
||||
push constant 140
|
||||
push constant 6
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push constant 163
|
||||
push constant 35
|
||||
push constant 178
|
||||
push constant 20
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push constant 174
|
||||
push constant 60
|
||||
push constant 194
|
||||
push constant 60
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push constant 163
|
||||
push constant 85
|
||||
push constant 178
|
||||
push constant 100
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push constant 140
|
||||
push constant 94
|
||||
push constant 140
|
||||
push constant 114
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push constant 117
|
||||
push constant 85
|
||||
push constant 102
|
||||
push constant 100
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push constant 106
|
||||
push constant 60
|
||||
push constant 86
|
||||
push constant 60
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push constant 117
|
||||
push constant 35
|
||||
push constant 102
|
||||
push constant 20
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+206
@@ -0,0 +1,206 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Screen.jack
|
||||
|
||||
/**
|
||||
* A library of functions for displaying graphics on the screen.
|
||||
* The Hack physical screen consists of 256 rows (indexed 0..255, top to bottom)
|
||||
* of 512 pixels each (indexed 0..511, left to right). The top left pixel on
|
||||
* the screen is indexed (0,0).
|
||||
*/
|
||||
class Screen {
|
||||
|
||||
static Array mem;
|
||||
static Array st;
|
||||
static boolean color;
|
||||
/** Initializes the Screen. */
|
||||
function void init() {
|
||||
var int a;
|
||||
let st = Array.new(16);
|
||||
let st[0] = 1;
|
||||
while (a < 15){
|
||||
let a = a + 1;
|
||||
let st[a] = st[a - 1] + st[a - 1];
|
||||
}
|
||||
let color = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Erases the entire screen. */
|
||||
function void clearScreen() {
|
||||
var int a;
|
||||
let a = 16384;
|
||||
while (a < 24575){
|
||||
let mem[a] = 0;
|
||||
let a = a + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Sets the current color, to be used for all subsequent drawXXX commands.
|
||||
* Black is represented by true, white by false. */
|
||||
function void setColor(boolean b) {
|
||||
let color = b;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws the (x,y) pixel, using the current color. */
|
||||
function void drawPixel(int x, int y) {
|
||||
var int value, address, bit, mem_block;
|
||||
if ((x > 511) | (x < 0) | (y > 255) | (y < 0)){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let mem_block = x / 16;
|
||||
let address = (32 * y) + mem_block + 16384;
|
||||
let value = mem[address];
|
||||
let bit = x - (mem_block * 16);
|
||||
if (color){
|
||||
let mem[address] = st[bit] | value;
|
||||
}
|
||||
else{
|
||||
let mem[address] = (~st[bit])& value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws a line from pixel (x1,y1) to pixel (x2,y2), using the current color. */
|
||||
function void drawLine(int x1, int y1, int x2, int y2) {
|
||||
var int diff, dx, dy, a, b;
|
||||
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
|
||||
do Sys.error(8);
|
||||
}
|
||||
let dx = x2 - x1;
|
||||
let dy = y2 - y1;
|
||||
if (dx = 0){
|
||||
if (dy > 0){
|
||||
while(~(b > dy)){
|
||||
do Screen.drawPixel(x1, y1 + b);
|
||||
let b = b + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else{
|
||||
while(~(b < dy)){
|
||||
do Screen.drawPixel(x1, y1 + b);
|
||||
let b = b - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dy = 0){
|
||||
if (dx > 0){
|
||||
while(~(a > dx)){
|
||||
do Screen.drawPixel(x1 + a, y1);
|
||||
let a = a + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else{
|
||||
while(~(a < dx)){
|
||||
do Screen.drawPixel(x1 + a, y1);
|
||||
let a = a - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dx < 0){
|
||||
if (dy < 0){
|
||||
while ((~(a < dx)) & (~(b < dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a - 1;
|
||||
let diff = diff - dy;
|
||||
}
|
||||
else{
|
||||
let b = b - 1;
|
||||
let diff = diff + dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
while ((~(a < dx)) & (~(b > dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a - 1;
|
||||
let diff = diff + dy;
|
||||
}
|
||||
else{
|
||||
let b = b + 1;
|
||||
let diff = diff + dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (dy < 0){
|
||||
while ((~(a > dx)) & (~(b < dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a + 1;
|
||||
let diff = diff - dy;
|
||||
}
|
||||
else{
|
||||
let b = b - 1;
|
||||
let diff = diff - dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
while ((~(a > dx)) & (~(b > dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a + 1;
|
||||
let diff = diff + dy;
|
||||
}
|
||||
else{
|
||||
let b = b + 1;
|
||||
let diff = diff - dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws a filled rectangle whose top left corner is (x1, y1)
|
||||
* and bottom right corner is (x2,y2), using the current color. */
|
||||
function void drawRectangle(int x1, int y1, int x2, int y2) {
|
||||
var int a, tmp;
|
||||
if (x1 > x2){
|
||||
let tmp = x1;
|
||||
let x1 = x2;
|
||||
let x2 = tmp;
|
||||
}
|
||||
if (y1 > y2){
|
||||
let tmp = y1;
|
||||
let y1 = y2;
|
||||
let y2 = tmp;
|
||||
}
|
||||
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
|
||||
do Sys.error(8);
|
||||
}
|
||||
let tmp = y2 - y1;
|
||||
while(a < tmp){
|
||||
do Screen.drawLine(x1, y1 + a, x2, y1 + a);
|
||||
let a = a + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws a filled circle of radius r<=181 around (x,y), using the current color. */
|
||||
function void drawCircle(int x, int y, int r) {
|
||||
var int dy, dx, tmp;
|
||||
if(r > 181){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let dy = - r;
|
||||
while (dy < r){
|
||||
let tmp = Math.sqrt((r * r) - (dy * dy));
|
||||
do Screen.drawLine(x - tmp, y + dy, x + tmp, y + dy);
|
||||
let dy = dy + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+656
@@ -0,0 +1,656 @@
|
||||
function Screen.init 1
|
||||
push constant 16
|
||||
call Array.new 1
|
||||
pop static 1
|
||||
push static 1
|
||||
push constant 0
|
||||
push constant 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
label L0
|
||||
push local 0
|
||||
push constant 15
|
||||
lt
|
||||
not
|
||||
if-goto L1
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
push static 1
|
||||
push local 0
|
||||
push static 1
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push static 1
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
goto L0
|
||||
label L1
|
||||
push constant 1
|
||||
neg
|
||||
pop static 2
|
||||
push constant 0
|
||||
return
|
||||
function Screen.clearScreen 1
|
||||
push constant 16384
|
||||
pop local 0
|
||||
label L2
|
||||
push local 0
|
||||
push constant 24575
|
||||
lt
|
||||
not
|
||||
if-goto L3
|
||||
push static 0
|
||||
push local 0
|
||||
push constant 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
goto L2
|
||||
label L3
|
||||
push constant 0
|
||||
return
|
||||
function Screen.setColor 0
|
||||
push argument 0
|
||||
pop static 2
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawPixel 4
|
||||
push argument 0
|
||||
push constant 511
|
||||
gt
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 1
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
not
|
||||
if-goto L4
|
||||
push constant 7
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L5
|
||||
label L4
|
||||
label L5
|
||||
push argument 0
|
||||
push constant 16
|
||||
call Math.divide 2
|
||||
pop local 3
|
||||
push constant 32
|
||||
push argument 1
|
||||
call Math.multiply 2
|
||||
push local 3
|
||||
add
|
||||
push constant 16384
|
||||
add
|
||||
pop local 1
|
||||
push static 0
|
||||
push local 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop local 0
|
||||
push argument 0
|
||||
push local 3
|
||||
push constant 16
|
||||
call Math.multiply 2
|
||||
sub
|
||||
pop local 2
|
||||
push static 2
|
||||
not
|
||||
if-goto L6
|
||||
push static 0
|
||||
push local 1
|
||||
push static 1
|
||||
push local 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 0
|
||||
or
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
goto L7
|
||||
label L6
|
||||
push static 0
|
||||
push local 1
|
||||
push static 1
|
||||
push local 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
not
|
||||
push local 0
|
||||
and
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
label L7
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawLine 5
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 2
|
||||
push constant 511
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 3
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
not
|
||||
if-goto L8
|
||||
push constant 8
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L9
|
||||
label L8
|
||||
label L9
|
||||
push argument 2
|
||||
push argument 0
|
||||
sub
|
||||
pop local 1
|
||||
push argument 3
|
||||
push argument 1
|
||||
sub
|
||||
pop local 2
|
||||
push local 1
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L10
|
||||
push local 2
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L11
|
||||
label L12
|
||||
push local 4
|
||||
push local 2
|
||||
gt
|
||||
not
|
||||
not
|
||||
if-goto L13
|
||||
push argument 0
|
||||
push argument 1
|
||||
push local 4
|
||||
add
|
||||
call Screen.drawPixel 2
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 1
|
||||
add
|
||||
pop local 4
|
||||
goto L12
|
||||
label L13
|
||||
push constant 0
|
||||
return
|
||||
goto L14
|
||||
label L11
|
||||
label L15
|
||||
push local 4
|
||||
push local 2
|
||||
lt
|
||||
not
|
||||
not
|
||||
if-goto L16
|
||||
push argument 0
|
||||
push argument 1
|
||||
push local 4
|
||||
add
|
||||
call Screen.drawPixel 2
|
||||
pop temp 0
|
||||
push local 4
|
||||
push constant 1
|
||||
sub
|
||||
pop local 4
|
||||
goto L15
|
||||
label L16
|
||||
push constant 0
|
||||
return
|
||||
label L14
|
||||
goto L17
|
||||
label L10
|
||||
label L17
|
||||
push local 2
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L18
|
||||
push local 1
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L19
|
||||
label L20
|
||||
push local 3
|
||||
push local 1
|
||||
gt
|
||||
not
|
||||
not
|
||||
if-goto L21
|
||||
push argument 0
|
||||
push local 3
|
||||
add
|
||||
push argument 1
|
||||
call Screen.drawPixel 2
|
||||
pop temp 0
|
||||
push local 3
|
||||
push constant 1
|
||||
add
|
||||
pop local 3
|
||||
goto L20
|
||||
label L21
|
||||
push constant 0
|
||||
return
|
||||
goto L22
|
||||
label L19
|
||||
label L23
|
||||
push local 3
|
||||
push local 1
|
||||
lt
|
||||
not
|
||||
not
|
||||
if-goto L24
|
||||
push argument 0
|
||||
push local 3
|
||||
add
|
||||
push argument 1
|
||||
call Screen.drawPixel 2
|
||||
pop temp 0
|
||||
push local 3
|
||||
push constant 1
|
||||
sub
|
||||
pop local 3
|
||||
goto L23
|
||||
label L24
|
||||
push constant 0
|
||||
return
|
||||
label L22
|
||||
goto L25
|
||||
label L18
|
||||
label L25
|
||||
push local 1
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L26
|
||||
push local 2
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L27
|
||||
label L28
|
||||
push local 3
|
||||
push local 1
|
||||
lt
|
||||
not
|
||||
push local 4
|
||||
push local 2
|
||||
lt
|
||||
not
|
||||
and
|
||||
not
|
||||
if-goto L29
|
||||
push argument 0
|
||||
push local 3
|
||||
add
|
||||
push argument 1
|
||||
push local 4
|
||||
add
|
||||
call Screen.drawPixel 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L30
|
||||
push local 3
|
||||
push constant 1
|
||||
sub
|
||||
pop local 3
|
||||
push local 0
|
||||
push local 2
|
||||
sub
|
||||
pop local 0
|
||||
goto L31
|
||||
label L30
|
||||
push local 4
|
||||
push constant 1
|
||||
sub
|
||||
pop local 4
|
||||
push local 0
|
||||
push local 1
|
||||
add
|
||||
pop local 0
|
||||
label L31
|
||||
goto L28
|
||||
label L29
|
||||
goto L32
|
||||
label L27
|
||||
label L33
|
||||
push local 3
|
||||
push local 1
|
||||
lt
|
||||
not
|
||||
push local 4
|
||||
push local 2
|
||||
gt
|
||||
not
|
||||
and
|
||||
not
|
||||
if-goto L34
|
||||
push argument 0
|
||||
push local 3
|
||||
add
|
||||
push argument 1
|
||||
push local 4
|
||||
add
|
||||
call Screen.drawPixel 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L35
|
||||
push local 3
|
||||
push constant 1
|
||||
sub
|
||||
pop local 3
|
||||
push local 0
|
||||
push local 2
|
||||
add
|
||||
pop local 0
|
||||
goto L36
|
||||
label L35
|
||||
push local 4
|
||||
push constant 1
|
||||
add
|
||||
pop local 4
|
||||
push local 0
|
||||
push local 1
|
||||
add
|
||||
pop local 0
|
||||
label L36
|
||||
goto L33
|
||||
label L34
|
||||
label L32
|
||||
goto L37
|
||||
label L26
|
||||
push local 2
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L38
|
||||
label L39
|
||||
push local 3
|
||||
push local 1
|
||||
gt
|
||||
not
|
||||
push local 4
|
||||
push local 2
|
||||
lt
|
||||
not
|
||||
and
|
||||
not
|
||||
if-goto L40
|
||||
push argument 0
|
||||
push local 3
|
||||
add
|
||||
push argument 1
|
||||
push local 4
|
||||
add
|
||||
call Screen.drawPixel 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L41
|
||||
push local 3
|
||||
push constant 1
|
||||
add
|
||||
pop local 3
|
||||
push local 0
|
||||
push local 2
|
||||
sub
|
||||
pop local 0
|
||||
goto L42
|
||||
label L41
|
||||
push local 4
|
||||
push constant 1
|
||||
sub
|
||||
pop local 4
|
||||
push local 0
|
||||
push local 1
|
||||
sub
|
||||
pop local 0
|
||||
label L42
|
||||
goto L39
|
||||
label L40
|
||||
goto L43
|
||||
label L38
|
||||
label L44
|
||||
push local 3
|
||||
push local 1
|
||||
gt
|
||||
not
|
||||
push local 4
|
||||
push local 2
|
||||
gt
|
||||
not
|
||||
and
|
||||
not
|
||||
if-goto L45
|
||||
push argument 0
|
||||
push local 3
|
||||
add
|
||||
push argument 1
|
||||
push local 4
|
||||
add
|
||||
call Screen.drawPixel 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L46
|
||||
push local 3
|
||||
push constant 1
|
||||
add
|
||||
pop local 3
|
||||
push local 0
|
||||
push local 2
|
||||
add
|
||||
pop local 0
|
||||
goto L47
|
||||
label L46
|
||||
push local 4
|
||||
push constant 1
|
||||
add
|
||||
pop local 4
|
||||
push local 0
|
||||
push local 1
|
||||
sub
|
||||
pop local 0
|
||||
label L47
|
||||
goto L44
|
||||
label L45
|
||||
label L43
|
||||
label L37
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawRectangle 2
|
||||
push argument 0
|
||||
push argument 2
|
||||
gt
|
||||
not
|
||||
if-goto L48
|
||||
push argument 0
|
||||
pop local 1
|
||||
push argument 2
|
||||
pop argument 0
|
||||
push local 1
|
||||
pop argument 2
|
||||
goto L49
|
||||
label L48
|
||||
label L49
|
||||
push argument 1
|
||||
push argument 3
|
||||
gt
|
||||
not
|
||||
if-goto L50
|
||||
push argument 1
|
||||
pop local 1
|
||||
push argument 3
|
||||
pop argument 1
|
||||
push local 1
|
||||
pop argument 3
|
||||
goto L51
|
||||
label L50
|
||||
label L51
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 2
|
||||
push constant 511
|
||||
gt
|
||||
or
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
push argument 3
|
||||
push constant 255
|
||||
gt
|
||||
or
|
||||
not
|
||||
if-goto L52
|
||||
push constant 8
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L53
|
||||
label L52
|
||||
label L53
|
||||
push argument 3
|
||||
push argument 1
|
||||
sub
|
||||
pop local 1
|
||||
label L54
|
||||
push local 0
|
||||
push local 1
|
||||
lt
|
||||
not
|
||||
if-goto L55
|
||||
push argument 0
|
||||
push argument 1
|
||||
push local 0
|
||||
add
|
||||
push argument 2
|
||||
push argument 1
|
||||
push local 0
|
||||
add
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
goto L54
|
||||
label L55
|
||||
push constant 0
|
||||
return
|
||||
function Screen.drawCircle 3
|
||||
push argument 2
|
||||
push constant 181
|
||||
gt
|
||||
not
|
||||
if-goto L56
|
||||
push constant 7
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L57
|
||||
label L56
|
||||
label L57
|
||||
push argument 2
|
||||
neg
|
||||
pop local 0
|
||||
label L58
|
||||
push local 0
|
||||
push argument 2
|
||||
lt
|
||||
not
|
||||
if-goto L59
|
||||
push argument 2
|
||||
push argument 2
|
||||
call Math.multiply 2
|
||||
push local 0
|
||||
push local 0
|
||||
call Math.multiply 2
|
||||
sub
|
||||
call Math.sqrt 1
|
||||
pop local 2
|
||||
push argument 0
|
||||
push local 2
|
||||
sub
|
||||
push argument 1
|
||||
push local 0
|
||||
add
|
||||
push argument 0
|
||||
push local 2
|
||||
add
|
||||
push argument 1
|
||||
push local 0
|
||||
add
|
||||
call Screen.drawLine 4
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
goto L58
|
||||
label L59
|
||||
push constant 0
|
||||
return
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
Executable
+148
@@ -0,0 +1,148 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/String.jack
|
||||
|
||||
/**
|
||||
* Represents character strings. In addition for constructing and disposing
|
||||
* strings, the class features methods for getting and setting individual
|
||||
* characters of the string, for erasing the string's last character,
|
||||
* for appending a character to the string's end, and more typical
|
||||
* string-oriented operations.
|
||||
*/
|
||||
class String {
|
||||
field Array str;
|
||||
field int length;
|
||||
static bool neg;
|
||||
|
||||
/** constructs a new empty string with a maximum length of maxLength
|
||||
* and initial length of 0. */
|
||||
constructor String new(int maxLength) {
|
||||
if (maxLength > 0){
|
||||
let str = Array.new(maxLength);
|
||||
}
|
||||
let length = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Disposes this string. */
|
||||
method void dispose() {
|
||||
if(length > 0){
|
||||
do str.dispose();
|
||||
}
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the current length of this string. */
|
||||
method int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Returns the character at the j-th location of this string. */
|
||||
method char charAt(int j) {
|
||||
if(j > length){
|
||||
do Sys.error(7);
|
||||
}
|
||||
return str[j];
|
||||
}
|
||||
|
||||
/** Sets the character at the j-th location of this string to c. */
|
||||
method void setCharAt(int j, char c) {
|
||||
if(j > length){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let str[j] = c;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Appends c to this string's end and returns this string. */
|
||||
method String appendChar(char c) {
|
||||
let str[length] = c;
|
||||
let length = length + 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Erases the last character from this string. */
|
||||
method void eraseLastChar() {
|
||||
let str[length] = 0;
|
||||
let length = length - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the integer value of this string,
|
||||
* until a non-digit character is detected. */
|
||||
method int intValue() {
|
||||
var int d, sum, i;
|
||||
var bool f;
|
||||
while(i < length){
|
||||
let d = str[i]; // kak da go zavyrtq v realen int
|
||||
if ((d > 47) & (d < 58)){
|
||||
let sum = (sum * 10) + (d - 48);
|
||||
}
|
||||
else{
|
||||
if((i = 0) & (d = 45)){
|
||||
let f = true;
|
||||
}
|
||||
else{
|
||||
let i = length;
|
||||
}
|
||||
}
|
||||
let i = i + 1;
|
||||
}
|
||||
if (f){
|
||||
return -sum;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/** Sets this string to hold a representation of the given value. */
|
||||
method void setInt(int val) {
|
||||
var int lastDigit, a, i;
|
||||
var char c;
|
||||
if(val < 0){
|
||||
let neg = true;
|
||||
let val = -val;
|
||||
}
|
||||
let a = val / 10;
|
||||
let lastDigit = val - (a * 10);
|
||||
let i = 48;
|
||||
while (i < 58){
|
||||
if (i = (48 + lastDigit)){
|
||||
let c = i;
|
||||
let i = 59;
|
||||
}
|
||||
let i = i + 1;
|
||||
}
|
||||
if (val < 10){
|
||||
let length = 0;
|
||||
if (neg){
|
||||
let neg = false;
|
||||
do this.appendChar("-");
|
||||
}
|
||||
|
||||
do this.appendChar(c);
|
||||
return;
|
||||
}
|
||||
else{
|
||||
do this.setInt(a);
|
||||
do this.appendChar(c);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the new line character. */
|
||||
function char newLine() {
|
||||
return 128;
|
||||
}
|
||||
|
||||
/** Returns the backspace character. */
|
||||
function char backSpace() {
|
||||
return 129;
|
||||
}
|
||||
|
||||
/** Returns the double quote (") character. */
|
||||
function char doubleQuote() {
|
||||
return 34;
|
||||
}
|
||||
}
|
||||
Executable
+350
@@ -0,0 +1,350 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from tokenizer import Tokenizer
|
||||
from vmwriter import VMWriter
|
||||
from symbol_table import SymbolTable
|
||||
|
||||
|
||||
# TODO add names to variables when you call for them, aka current_vm_append(thingtobeappended=blablac)
|
||||
|
||||
class CompilationEngine:
|
||||
def __init__(self, tokenizer, full_path_vm):
|
||||
self.string = self.sub_type = self.class_name = self.function_type = ''
|
||||
self.tab = self.recursion_index = 0
|
||||
self.tokenizer = tokenizer
|
||||
self.sym_table = []
|
||||
self.vmwriter = VMWriter(full_path_vm)
|
||||
self.current_vm = [] # used to reverse some of the commands, eg a+b need to be a b +
|
||||
|
||||
def search_kind_of_sym(self, current_vm):
|
||||
if self.sym_table[-1].kind_of(current_vm) is not None:
|
||||
return self.sym_table[-1].kind_of(current_vm), self.sym_table[-1].index_of(current_vm)
|
||||
for i in range(len(self.sym_table) - 2, -1,
|
||||
-1): # start from the amount of sym_tables -2 so it starts from one below the current,
|
||||
# until it is bigger than -1, walking it backwards
|
||||
if self.sym_table[i].kind_of(current_vm) in ('static', 'this'):
|
||||
return self.sym_table[i].kind_of(current_vm), self.sym_table[i].index_of(current_vm)
|
||||
|
||||
def search_type_of_sym(self, current_vm):
|
||||
for i in range(len(self.sym_table) - 1, -1, -1):
|
||||
if self.sym_table[i].type_of(current_vm) is not None:
|
||||
return self.sym_table[i].type_of(current_vm)
|
||||
|
||||
def write_token(self):
|
||||
if self.tokenizer.token_type() == 'stringConstant':
|
||||
self.string += ' ' * self.tab + '<' + self.tokenizer.token_type() + '> ' + self.tokenizer.token.strip(
|
||||
'"') + ' </' + self.tokenizer.token_type() + '>\n'
|
||||
else:
|
||||
self.string += ' ' * self.tab + '<' + self.tokenizer.token_type() + '> ' + self.tokenizer.token + ' </' \
|
||||
+ self.tokenizer.token_type() + '>\n'
|
||||
|
||||
def compile_class(self):
|
||||
self.sym_table.append(SymbolTable())
|
||||
self.tokenizer.advance() # class ->
|
||||
self.tokenizer.advance() # type ->
|
||||
self.class_name = self.tokenizer.token
|
||||
self.tokenizer.advance() # name ->
|
||||
self.tokenizer.advance() # { ->
|
||||
while self.tokenizer.token != '}':
|
||||
if self.tokenizer.token in ['static', 'field']:
|
||||
self.compile_class_var_dec()
|
||||
if self.tokenizer.token in ['constructor', 'function', 'method']:
|
||||
self.compile_subroutine()
|
||||
self.tokenizer.advance()
|
||||
self.sym_table.pop()
|
||||
self.vmwriter.close_vm_file()
|
||||
|
||||
def compile_class_var_dec(self):
|
||||
var_kind = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_type = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
while self.tokenizer.token == ',':
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
self.tokenizer.advance()
|
||||
|
||||
def compile_subroutine(self):
|
||||
self.sym_table.append(SymbolTable())
|
||||
self.sub_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine type(function|method|constructor) ->
|
||||
self.function_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine kind(int|void|etc..) ->
|
||||
sub_name = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine name ->
|
||||
self.tokenizer.advance() # ( ->
|
||||
if self.sub_type == 'method':
|
||||
self.sym_table[-1].start_subroutine('this', self.class_name)
|
||||
self.compile_parameter_list()
|
||||
self.tokenizer.advance() # { ->
|
||||
while self.tokenizer.token == 'var': # create only symbol teable entries
|
||||
self.compile_var_dec()
|
||||
if self.sub_type == 'constructor':
|
||||
self.vmwriter.write_function(f'{self.class_name}.{sub_name}', self.sym_table[-1].var_count('var'))
|
||||
self.vmwriter.write_push('constant', self.sym_table[-2].var_count('field'))
|
||||
self.vmwriter.write_call('Memory.alloc', 1)
|
||||
self.vmwriter.write_pop('pointer', 0)
|
||||
elif self.sub_type == 'method':
|
||||
self.vmwriter.write_function(f'{self.class_name}.{sub_name}', self.sym_table[-1].var_count('var'))
|
||||
self.vmwriter.write_push('argument', 0)
|
||||
self.vmwriter.write_pop('pointer', 0)
|
||||
else:
|
||||
self.vmwriter.write_function(f'{self.class_name}.{sub_name}', self.sym_table[-1].var_count('var'))
|
||||
while self.tokenizer.token != '}':
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance()
|
||||
self.sym_table.pop()
|
||||
|
||||
def compile_parameter_list(self):
|
||||
if self.tokenizer.token != ')':
|
||||
var_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # var ype ->
|
||||
var_name = self.tokenizer.token
|
||||
self.sym_table[-1].define(var_name, var_type, 'argument')
|
||||
self.tokenizer.advance() # var name ->
|
||||
while self.tokenizer.token == ',':
|
||||
self.tokenizer.advance() # , ->
|
||||
var_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # type ->
|
||||
var_name = self.tokenizer.token
|
||||
self.sym_table[-1].define(var_name, var_type, 'argument')
|
||||
self.tokenizer.advance() # name ->
|
||||
self.tokenizer.advance() # )->
|
||||
|
||||
def compile_var_dec(self):
|
||||
var_kind = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_type = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
while self.tokenizer.token == ',':
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
self.tokenizer.advance()
|
||||
|
||||
def compile_statements(self):
|
||||
while True:
|
||||
if self.tokenizer.token == 'let':
|
||||
self.compile_let()
|
||||
elif self.tokenizer.token == 'if':
|
||||
self.compile_if()
|
||||
elif self.tokenizer.token == 'while':
|
||||
self.compile_while()
|
||||
elif self.tokenizer.token == 'do':
|
||||
self.compile_do()
|
||||
elif self.tokenizer.token == 'return':
|
||||
self.compile_return()
|
||||
else:
|
||||
break
|
||||
|
||||
def compile_do(self):
|
||||
self.tokenizer.advance() # do ->
|
||||
class_name = self.tokenizer.token
|
||||
self.tokenizer.advance() # name ->
|
||||
if self.tokenizer.token == '(': # method
|
||||
self.vmwriter.write_push('pointer', 0)
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
self.vmwriter.write_call(f'{self.class_name}.{class_name}', count + 1)
|
||||
elif self.tokenizer.token == '.': # method or function
|
||||
self.tokenizer.advance() # . ->
|
||||
fname = f'{class_name}.{self.tokenizer.token}'
|
||||
sname = f'{self.search_type_of_sym(class_name)}.{self.tokenizer.token}'
|
||||
self.tokenizer.advance() # name ->
|
||||
if self.search_kind_of_sym(class_name) is not None:
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(class_name))
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
if self.search_kind_of_sym(class_name) is not None:
|
||||
self.vmwriter.write_call(f'{sname}', count + 1)
|
||||
else:
|
||||
self.vmwriter.write_call(f'{fname}', count)
|
||||
self.vmwriter.write_pop('temp', '0')
|
||||
self.tokenizer.advance() # ; ->
|
||||
|
||||
def compile_let(self):
|
||||
flag_array = 0
|
||||
self.tokenizer.advance() # let ->
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
self.tokenizer.advance() # var_name ->
|
||||
if self.tokenizer.token == '[':
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
self.tokenizer.advance() # [ ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ] ->
|
||||
flag_array = 1
|
||||
self.tokenizer.advance() # = ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ; ->
|
||||
if flag_array == 0:
|
||||
self.vmwriter.write_pop(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
else:
|
||||
self.vmwriter.write_pop('temp', 1)
|
||||
self.vmwriter.write_arithmetic('+')
|
||||
self.vmwriter.write_pop('pointer', 1)
|
||||
self.vmwriter.write_push('temp', 1)
|
||||
self.vmwriter.write_pop('that', 0)
|
||||
self.current_vm.pop()
|
||||
|
||||
def compile_while(self):
|
||||
self.tokenizer.advance() # while ->
|
||||
label1 = self.vmwriter.label_index
|
||||
self.vmwriter.write_lable(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.tokenizer.advance() # ( ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ) ->
|
||||
label2 = self.vmwriter.label_index
|
||||
self.vmwriter.write_if(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.tokenizer.advance() # { ->
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance() # } ->
|
||||
self.vmwriter.write_goto(label1)
|
||||
self.vmwriter.write_lable(label2)
|
||||
|
||||
def compile_return(self):
|
||||
self.tokenizer.advance() # return ->
|
||||
if self.tokenizer.token != ';':
|
||||
self.compile_expression()
|
||||
self.vmwriter.write_return(self.function_type)
|
||||
self.tokenizer.advance() # ; ->
|
||||
|
||||
def compile_if(self):
|
||||
self.tokenizer.advance() # if ->
|
||||
self.tokenizer.advance() # ( ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ) ->
|
||||
label1 = self.vmwriter.label_index
|
||||
self.vmwriter.write_if(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.tokenizer.advance() # { ->
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance() # } ->
|
||||
label2 = self.vmwriter.label_index
|
||||
self.vmwriter.write_goto(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.vmwriter.write_lable(label1)
|
||||
if self.tokenizer.token == 'else':
|
||||
self.tokenizer.advance() # else ->
|
||||
self.tokenizer.advance() # { ->
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance() # } ->
|
||||
self.vmwriter.write_lable(label2)
|
||||
|
||||
def compile_expression(self):
|
||||
self.compile_term()
|
||||
while self.tokenizer.token in ['+', '-', '*', '/', '|', '=', '>', '<', '&']:
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
self.tokenizer.advance() # symbol ->
|
||||
self.compile_term()
|
||||
self.vmwriter.write_arithmetic(self.current_vm[-1])
|
||||
self.current_vm.pop()
|
||||
|
||||
def compile_term(self):
|
||||
if self.tokenizer.token == '(': # expression ()
|
||||
self.tokenizer.advance() # ( ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ) ->
|
||||
elif self.tokenizer.token in ['~', '-']: # uniry op
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
tmp = 'neg' if self.tokenizer.token == '-' else self.tokenizer.token
|
||||
self.tokenizer.advance() # ~ or - ->
|
||||
self.compile_term()
|
||||
self.vmwriter.write_arithmetic(tmp)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type() != 'symbol':
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
self.tokenizer.advance() # integer, string, keyword, varnname, subroutine_name, class_name, var_name ->
|
||||
if self.tokenizer.token == '[': # Array
|
||||
self.tokenizer.advance() # [ ->
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
self.current_vm.pop()
|
||||
self.compile_expression()
|
||||
self.vmwriter.write_arithmetic('+')
|
||||
self.vmwriter.write_pop('pointer', 1)
|
||||
self.vmwriter.write_push('that', 0)
|
||||
self.tokenizer.advance() # ] ->
|
||||
elif self.tokenizer.token == '(': # subroutine_name ()
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
self.vmwriter.write_call(f'{self.class_name}.{self.current_vm[-1]}', count)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token == '.': # method
|
||||
if self.search_type_of_sym(self.current_vm[-1]) is not None:
|
||||
flag = 1
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
else:
|
||||
flag = 0
|
||||
self.tokenizer.advance() # . ->
|
||||
fname = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine name ->
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
if flag == 1:
|
||||
self.vmwriter.write_call(f'{self.search_type_of_sym(self.current_vm[-1])}.{fname}', count + 1)
|
||||
else:
|
||||
self.vmwriter.write_call(f'{self.current_vm[-1]}.{fname}', count)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type(self.current_vm[-1]) == 'stringConstant':
|
||||
self.vmwriter.write_push('constant', len(self.current_vm[-1].strip('"')))
|
||||
self.vmwriter.write_call('String.new', 1)
|
||||
for index, item in enumerate(self.current_vm[-1].strip('"')):
|
||||
self.vmwriter.write_push('constant', ord(item))
|
||||
self.vmwriter.write_call('String.appendChar', 2)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type(self.current_vm[-1]) == 'integerConstant':
|
||||
self.vmwriter.write_push('constant', self.current_vm[-1])
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type(self.current_vm[-1]) == 'identifier':
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'true':
|
||||
self.vmwriter.write_push('constant', '1')
|
||||
self.vmwriter.write_arithmetic('neg')
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'false' or self.current_vm[-1] == 'null':
|
||||
self.vmwriter.write_push('constant', '0')
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'this':
|
||||
self.vmwriter.write_push('pointer', '0')
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'that':
|
||||
self.vmwriter.write_push('pointer', '1')
|
||||
self.current_vm.pop()
|
||||
|
||||
def compile_expression_list(self):
|
||||
count_exp = 0
|
||||
if self.tokenizer.token in ['(', '~', '-'] or self.tokenizer.token_type() != 'symbol':
|
||||
count_exp += 1
|
||||
self.compile_expression()
|
||||
while self.tokenizer.token == ',':
|
||||
count_exp += 1
|
||||
self.tokenizer.advance() # ,
|
||||
self.compile_expression()
|
||||
return count_exp
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
path = os.getcwd()
|
||||
for root, dirs, files in os.walk(path, topdown=False):
|
||||
for name in files:
|
||||
if name[-4:] == 'jack':
|
||||
tokenizer_main = Tokenizer()
|
||||
tokenizer_main.clear_file(Path(root, name))
|
||||
full_path = Path(root, name[:-4] + 'vm')
|
||||
comp_eng_main = CompilationEngine(tokenizer_main, full_path)
|
||||
comp_eng_main.compile_class()
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/StringTest/Main.jack
|
||||
|
||||
/** Test program for the OS String class. */
|
||||
class Main {
|
||||
|
||||
/** Performs various string manipulations and displays their results. */
|
||||
function void main() {
|
||||
var String s;
|
||||
var String i;
|
||||
|
||||
let s = String.new(0); // a zero-capacity string should be supported
|
||||
do s.dispose();
|
||||
|
||||
let s = String.new(6); // capacity 6, make sure that length 5 is displayed
|
||||
let s = s.appendChar(97);
|
||||
let s = s.appendChar(98);
|
||||
let s = s.appendChar(99);
|
||||
let s = s.appendChar(100);
|
||||
let s = s.appendChar(101);
|
||||
do Output.printString("new: ");
|
||||
do Output.printString(s); // new, appendChar: abcde
|
||||
do Output.println();
|
||||
|
||||
let i = String.new(6);
|
||||
do i.setInt(12345);
|
||||
do Output.printString("setInt: ");
|
||||
do Output.printString(i); // setInt: 12345
|
||||
do Output.println();
|
||||
|
||||
do i.setInt(-32767);
|
||||
do Output.printString("setInt: ");
|
||||
do Output.printString(i); // setInt: -32767
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("length: ");
|
||||
do Output.printInt(s.length()); // length: 5
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("charAt[2]: ");
|
||||
do Output.printInt(s.charAt(2)); // charAt[2]: 99
|
||||
do Output.println();
|
||||
|
||||
do s.setCharAt(2, 45);
|
||||
do Output.printString("setCharAt(2,'-'): ");
|
||||
do Output.printString(s); // setCharAt(2,'-'): ab-de
|
||||
do Output.println();
|
||||
|
||||
do s.eraseLastChar();
|
||||
do Output.printString("eraseLastChar: ");
|
||||
do Output.printString(s); // eraseLastChar: ab-d
|
||||
do Output.println();
|
||||
|
||||
let s = "456";
|
||||
do Output.printString("intValue: ");
|
||||
do Output.printInt(s.intValue()); // intValue: 456
|
||||
do Output.println();
|
||||
|
||||
let s = "-32123";
|
||||
do Output.printString("intValue: ");
|
||||
do Output.printInt(s.intValue()); // intValue: -32123
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("backSpace: ");
|
||||
do Output.printInt(String.backSpace()); // backSpace: 129
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("doubleQuote: ");
|
||||
do Output.printInt(String.doubleQuote());// doubleQuote: 34
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("newLine: ");
|
||||
do Output.printInt(String.newLine()); // newLine: 128
|
||||
do Output.println();
|
||||
|
||||
do i.dispose();
|
||||
do s.dispose();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+447
@@ -0,0 +1,447 @@
|
||||
function Main.main 2
|
||||
push constant 0
|
||||
call String.new 1
|
||||
pop local 0
|
||||
push local 0
|
||||
call String.dispose 1
|
||||
pop temp 0
|
||||
push constant 6
|
||||
call String.new 1
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 98
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push constant 5
|
||||
call String.new 1
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 119
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 6
|
||||
call String.new 1
|
||||
pop local 1
|
||||
push local 1
|
||||
push constant 12345
|
||||
call String.setInt 2
|
||||
pop temp 0
|
||||
push constant 8
|
||||
call String.new 1
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 73
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push local 1
|
||||
push constant 32767
|
||||
neg
|
||||
call String.setInt 2
|
||||
pop temp 0
|
||||
push constant 8
|
||||
call String.new 1
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 73
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 8
|
||||
call String.new 1
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 103
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call String.length 1
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 11
|
||||
call String.new 1
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 65
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 91
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 93
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 2
|
||||
call String.charAt 2
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 2
|
||||
push constant 45
|
||||
call String.setCharAt 3
|
||||
pop temp 0
|
||||
push constant 18
|
||||
call String.new 1
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 67
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 65
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 40
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 44
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 45
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 41
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push local 0
|
||||
call String.eraseLastChar 1
|
||||
pop temp 0
|
||||
push constant 15
|
||||
call String.new 1
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 76
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 67
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 3
|
||||
call String.new 1
|
||||
push constant 52
|
||||
call String.appendChar 2
|
||||
push constant 53
|
||||
call String.appendChar 2
|
||||
push constant 54
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push constant 10
|
||||
call String.new 1
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 86
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call String.intValue 1
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 6
|
||||
call String.new 1
|
||||
push constant 45
|
||||
call String.appendChar 2
|
||||
push constant 51
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 49
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 51
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push constant 10
|
||||
call String.new 1
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 86
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call String.intValue 1
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 11
|
||||
call String.new 1
|
||||
push constant 98
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 107
|
||||
call String.appendChar 2
|
||||
push constant 83
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call String.backSpace 0
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 13
|
||||
call String.new 1
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 98
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 81
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call String.doubleQuote 0
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 9
|
||||
call String.new 1
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 119
|
||||
call String.appendChar 2
|
||||
push constant 76
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call String.newLine 0
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push local 1
|
||||
call String.dispose 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call String.dispose 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+147
@@ -0,0 +1,147 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/String.jack
|
||||
|
||||
/**
|
||||
* Represents character strings. In addition for constructing and disposing
|
||||
* strings, the class features methods for getting and setting individual
|
||||
* characters of the string, for erasing the string's last character,
|
||||
* for appending a character to the string's end, and more typical
|
||||
* string-oriented operations.
|
||||
*/
|
||||
class String {
|
||||
field Array str;
|
||||
field int length;
|
||||
static bool neg;
|
||||
|
||||
/** constructs a new empty string with a maximum length of maxLength
|
||||
* and initial length of 0. */
|
||||
constructor String new(int maxLength) {
|
||||
if (maxLength > 0){
|
||||
let str = Array.new(maxLength);
|
||||
}
|
||||
let length = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Disposes this string. */
|
||||
method void dispose() {
|
||||
if(length > 0){
|
||||
do str.dispose();
|
||||
}
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the current length of this string. */
|
||||
method int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Returns the character at the j-th location of this string. */
|
||||
method char charAt(int j) {
|
||||
if(j > length){
|
||||
do Sys.error(7);
|
||||
}
|
||||
return str[j];
|
||||
}
|
||||
|
||||
/** Sets the character at the j-th location of this string to c. */
|
||||
method void setCharAt(int j, char c) {
|
||||
if(j > length){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let str[j] = c;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Appends c to this string's end and returns this string. */
|
||||
method String appendChar(char c) {
|
||||
let str[length] = c;
|
||||
let length = length + 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Erases the last character from this string. */
|
||||
method void eraseLastChar() {
|
||||
let str[length] = 0;
|
||||
let length = length - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the integer value of this string,
|
||||
* until a non-digit character is detected. */
|
||||
method int intValue() {
|
||||
var int d, sum, i;
|
||||
var bool f;
|
||||
while(i < length){
|
||||
let d = str[i]; // kak da go zavyrtq v realen int
|
||||
if ((d > 47) & (d < 58)){
|
||||
let sum = (sum * 10) + (d - 48);
|
||||
}
|
||||
else{
|
||||
if((i = 0) & (d = 45)){
|
||||
let f = true;
|
||||
}
|
||||
else{
|
||||
let i = length;
|
||||
}
|
||||
}
|
||||
let i = i + 1;
|
||||
}
|
||||
if (f){
|
||||
return -sum;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/** Sets this string to hold a representation of the given value. */
|
||||
method void setInt(int val) {
|
||||
var int lastDigit, a, i;
|
||||
var char c;
|
||||
if(val < 0){
|
||||
let neg = true;
|
||||
let val = -val;
|
||||
}
|
||||
let a = val / 10;
|
||||
let lastDigit = val - (a * 10);
|
||||
let i = 48;
|
||||
while (i < 58){
|
||||
if (i = (48 + lastDigit)){
|
||||
let c = i;
|
||||
let i = 59;
|
||||
}
|
||||
let i = i + 1;
|
||||
}
|
||||
if (val < 10){
|
||||
let length = 0;
|
||||
if (neg){
|
||||
let neg = false;
|
||||
do this.appendChar("-");
|
||||
}
|
||||
do this.appendChar(c);
|
||||
return;
|
||||
}
|
||||
else{
|
||||
do this.setInt(a);
|
||||
do this.appendChar(c);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the new line character. */
|
||||
function char newLine() {
|
||||
return 128;
|
||||
}
|
||||
|
||||
/** Returns the backspace character. */
|
||||
function char backSpace() {
|
||||
return 129;
|
||||
}
|
||||
|
||||
/** Returns the double quote (") character. */
|
||||
function char doubleQuote() {
|
||||
return 34;
|
||||
}
|
||||
}
|
||||
Executable
+295
@@ -0,0 +1,295 @@
|
||||
function String.new 0
|
||||
push constant 2
|
||||
call Memory.alloc 1
|
||||
pop pointer 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L0
|
||||
push argument 0
|
||||
call Array.new 1
|
||||
pop this 0
|
||||
goto L1
|
||||
label L0
|
||||
label L1
|
||||
push constant 0
|
||||
pop this 1
|
||||
push pointer 0
|
||||
return
|
||||
function String.dispose 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 1
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L2
|
||||
push this 0
|
||||
call Array.dispose 1
|
||||
pop temp 0
|
||||
goto L3
|
||||
label L2
|
||||
label L3
|
||||
push pointer 0
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function String.length 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 1
|
||||
return
|
||||
function String.charAt 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push argument 1
|
||||
push this 1
|
||||
gt
|
||||
not
|
||||
if-goto L4
|
||||
push constant 7
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L5
|
||||
label L4
|
||||
label L5
|
||||
push this 0
|
||||
push argument 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
return
|
||||
function String.setCharAt 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push argument 1
|
||||
push this 1
|
||||
gt
|
||||
not
|
||||
if-goto L6
|
||||
push constant 7
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L7
|
||||
label L6
|
||||
label L7
|
||||
push this 0
|
||||
push argument 1
|
||||
push argument 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
function String.appendChar 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
push this 1
|
||||
push argument 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push this 1
|
||||
push constant 1
|
||||
add
|
||||
pop this 1
|
||||
push pointer 0
|
||||
return
|
||||
function String.eraseLastChar 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
push this 1
|
||||
push constant 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push this 1
|
||||
push constant 1
|
||||
sub
|
||||
pop this 1
|
||||
push constant 0
|
||||
return
|
||||
function String.intValue 4
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
label L8
|
||||
push local 2
|
||||
push this 1
|
||||
lt
|
||||
not
|
||||
if-goto L9
|
||||
push this 0
|
||||
push local 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 47
|
||||
gt
|
||||
push local 0
|
||||
push constant 58
|
||||
lt
|
||||
and
|
||||
not
|
||||
if-goto L10
|
||||
push local 1
|
||||
push constant 10
|
||||
call Math.multiply 2
|
||||
push local 0
|
||||
push constant 48
|
||||
sub
|
||||
add
|
||||
pop local 1
|
||||
goto L11
|
||||
label L10
|
||||
push local 2
|
||||
push constant 0
|
||||
eq
|
||||
push local 0
|
||||
push constant 45
|
||||
eq
|
||||
and
|
||||
not
|
||||
if-goto L12
|
||||
push constant 1
|
||||
neg
|
||||
pop local 3
|
||||
goto L13
|
||||
label L12
|
||||
push this 1
|
||||
pop local 2
|
||||
label L13
|
||||
label L11
|
||||
push local 2
|
||||
push constant 1
|
||||
add
|
||||
pop local 2
|
||||
goto L8
|
||||
label L9
|
||||
push local 3
|
||||
not
|
||||
if-goto L14
|
||||
push local 1
|
||||
neg
|
||||
return
|
||||
goto L15
|
||||
label L14
|
||||
label L15
|
||||
push local 1
|
||||
return
|
||||
function String.setInt 4
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L16
|
||||
push constant 1
|
||||
neg
|
||||
pop static 0
|
||||
push argument 1
|
||||
neg
|
||||
pop argument 1
|
||||
goto L17
|
||||
label L16
|
||||
label L17
|
||||
push argument 1
|
||||
push constant 10
|
||||
call Math.divide 2
|
||||
pop local 1
|
||||
push argument 1
|
||||
push local 1
|
||||
push constant 10
|
||||
call Math.multiply 2
|
||||
sub
|
||||
pop local 0
|
||||
push constant 48
|
||||
pop local 2
|
||||
label L18
|
||||
push local 2
|
||||
push constant 58
|
||||
lt
|
||||
not
|
||||
if-goto L19
|
||||
push local 2
|
||||
push constant 48
|
||||
push local 0
|
||||
add
|
||||
eq
|
||||
not
|
||||
if-goto L20
|
||||
push local 2
|
||||
pop local 3
|
||||
push constant 59
|
||||
pop local 2
|
||||
goto L21
|
||||
label L20
|
||||
label L21
|
||||
push local 2
|
||||
push constant 1
|
||||
add
|
||||
pop local 2
|
||||
goto L18
|
||||
label L19
|
||||
push argument 1
|
||||
push constant 10
|
||||
lt
|
||||
not
|
||||
if-goto L22
|
||||
push constant 0
|
||||
pop this 1
|
||||
push static 0
|
||||
not
|
||||
if-goto L23
|
||||
push constant 0
|
||||
pop static 0
|
||||
push argument 0
|
||||
push constant 1
|
||||
call String.new 1
|
||||
push constant 45
|
||||
call String.appendChar 2
|
||||
call String.appendChar 2
|
||||
pop temp 0
|
||||
goto L24
|
||||
label L23
|
||||
label L24
|
||||
push argument 0
|
||||
push local 3
|
||||
call String.appendChar 2
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
goto L25
|
||||
label L22
|
||||
push argument 0
|
||||
push local 1
|
||||
call String.setInt 2
|
||||
pop temp 0
|
||||
push argument 0
|
||||
push local 3
|
||||
call String.appendChar 2
|
||||
pop temp 0
|
||||
label L25
|
||||
push constant 0
|
||||
return
|
||||
function String.newLine 0
|
||||
push constant 128
|
||||
return
|
||||
function String.backSpace 0
|
||||
push constant 129
|
||||
return
|
||||
function String.doubleQuote 0
|
||||
push constant 34
|
||||
return
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 7.9 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
+62
@@ -0,0 +1,62 @@
|
||||
class Symbol:
|
||||
def __init__(self):
|
||||
self.s_name = ''
|
||||
self.s_kind = ''
|
||||
self.s_type = ''
|
||||
self.s_index = 0
|
||||
|
||||
|
||||
class SymbolTable:
|
||||
def __init__(self):
|
||||
self.sym = []
|
||||
|
||||
def define(self, s_name, s_type, s_kind):
|
||||
self.sym.append(Symbol())
|
||||
self.sym[-1].s_name = s_name
|
||||
self.sym[-1].s_type = s_type
|
||||
self.sym[-1].s_kind = s_kind
|
||||
self.sym[-1].s_index = self.var_count(s_kind) - 1
|
||||
|
||||
def start_subroutine(self, s_name, s_type):
|
||||
self.sym.append(Symbol())
|
||||
self.sym[-1].s_name = s_name
|
||||
self.sym[-1].s_type = s_type
|
||||
self.sym[-1].s_kind = 'argument'
|
||||
self.sym[-1].s_index = 0
|
||||
|
||||
def start_class(self, s_name, s_type):
|
||||
self.sym.append(Symbol())
|
||||
self.sym[-1].s_name = 'this'
|
||||
self.sym[-1].s_type = s_type
|
||||
self.sym[-1].s_kind = 'field'
|
||||
self.sym[-1].s_index = 0
|
||||
|
||||
def var_count(self, s_kind):
|
||||
count = 0 # it is -1 so the first index is 0
|
||||
for i in self.sym:
|
||||
if i.s_kind == s_kind:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def kind_of(self, s_name):
|
||||
for i in self.sym:
|
||||
if i.s_name == s_name:
|
||||
if i.s_kind == 'var':
|
||||
return 'local'
|
||||
elif i.s_kind == 'field':
|
||||
return 'this'
|
||||
else:
|
||||
return i.s_kind
|
||||
return None
|
||||
|
||||
def type_of(self, s_name):
|
||||
for i in self.sym:
|
||||
if i.s_name == s_name:
|
||||
return i.s_type
|
||||
return None
|
||||
|
||||
def index_of(self, s_name):
|
||||
for i in self.sym:
|
||||
if i.s_name == s_name:
|
||||
return i.s_index
|
||||
return None
|
||||
Executable
+78
@@ -0,0 +1,78 @@
|
||||
import re
|
||||
|
||||
|
||||
class Tokenizer:
|
||||
|
||||
def __init__(self):
|
||||
self.i = 0
|
||||
self.file = ''
|
||||
self.symbols = ('(', ')', '[', ']', '}', '{', '>', '<', '=', '*', '+', '-', '/', '.', ';', ',', '&', '|',
|
||||
'~')
|
||||
self.key_word = (
|
||||
'class', 'method', 'function', 'constructor', 'int', 'boolean', 'char', 'void', 'var', 'static', 'field',
|
||||
'let', 'do', 'if', 'else', 'while', 'return', 'true', 'false', 'null', 'this')
|
||||
self.token = ''
|
||||
|
||||
def token_type(self, token=None):
|
||||
if token is None:
|
||||
token = self.token
|
||||
if token is None or token == '':
|
||||
return None
|
||||
if token in self.key_word:
|
||||
return 'keyword'
|
||||
elif token[0] == '"':
|
||||
return 'stringConstant'
|
||||
elif re.match(r"\d+", token):
|
||||
return 'integerConstant'
|
||||
elif token in self.symbols:
|
||||
return 'symbol'
|
||||
else:
|
||||
return 'identifier'
|
||||
|
||||
def advance(self):
|
||||
token = ''
|
||||
i = self.i
|
||||
while i < len(self.file):
|
||||
if re.match(r'\s', self.file[i]):
|
||||
i = i + 1
|
||||
continue
|
||||
else:
|
||||
if self.file[i] in self.symbols:
|
||||
self.token = self.file[i]
|
||||
self.i = i + 1
|
||||
return
|
||||
elif self.file[i] == '"':
|
||||
i += 1
|
||||
while self.file[i] != '"':
|
||||
token += self.file[i]
|
||||
i += 1
|
||||
self.i = i + 1
|
||||
self.token = '"' + token + '"'
|
||||
return
|
||||
else:
|
||||
while re.match(r'\w', self.file[i]):
|
||||
token += self.file[i]
|
||||
if i + 1 > len(self.file) - 1:
|
||||
break
|
||||
i += 1
|
||||
self.i = i
|
||||
self.token = token
|
||||
return
|
||||
|
||||
def clear_file(self, directory):
|
||||
with open(directory, "r") as my_file:
|
||||
txt = my_file.read()
|
||||
txt = re.sub(r"//.*", "", txt)
|
||||
txt = re.sub(r"/[*][*].*[*]/", "", txt)
|
||||
i = 0
|
||||
# TODO this should be a regex
|
||||
while i < len(txt):
|
||||
if txt[i] == '/' and txt[i + 1] == '*' and txt[i + 2] == '*':
|
||||
start = i
|
||||
while txt[i] != '*' or txt[i + 1] != '/':
|
||||
i += 1
|
||||
stop = i + 2
|
||||
txt = txt[:start] + txt[stop:len(txt)]
|
||||
i = start - 1
|
||||
i += 1
|
||||
self.file = txt
|
||||
Executable
+75
@@ -0,0 +1,75 @@
|
||||
class VMWriter:
|
||||
def __init__(self, vm_path):
|
||||
self.my_vm = open(vm_path, "w+")
|
||||
self.label_index = 0
|
||||
|
||||
def write_push(self, segment, index):
|
||||
self.my_vm.write(f'push {segment} {index}\n')
|
||||
print(f'push {segment} {index}')
|
||||
|
||||
def write_lable(self, label):
|
||||
self.my_vm.write(f'label L{label}\n')
|
||||
print(f'label L{label}')
|
||||
|
||||
def write_arithmetic(self, command):
|
||||
if command == '+':
|
||||
self.my_vm.write('add\n')
|
||||
print('add')
|
||||
elif command == '-':
|
||||
self.my_vm.write('sub\n')
|
||||
print('sub')
|
||||
elif command == 'neg':
|
||||
self.my_vm.write('neg\n')
|
||||
print('neg')
|
||||
elif command == '=':
|
||||
self.my_vm.write('eq\n')
|
||||
print('eq')
|
||||
elif command == '>':
|
||||
self.my_vm.write('gt\n')
|
||||
print('gt')
|
||||
elif command == '<':
|
||||
self.my_vm.write('lt\n')
|
||||
print('lt')
|
||||
elif command == '&':
|
||||
self.my_vm.write('and\n')
|
||||
print('and')
|
||||
elif command == '|':
|
||||
self.my_vm.write('or\n')
|
||||
print('or')
|
||||
elif command == '~':
|
||||
self.my_vm.write('not\n')
|
||||
print('not')
|
||||
elif command == '*':
|
||||
self.write_call('Math.multiply', 2)
|
||||
elif command == '/':
|
||||
self.write_call('Math.divide', 2)
|
||||
|
||||
def write_pop(self, segment, index):
|
||||
print(f'pop {segment} {index}')
|
||||
self.my_vm.write(f'pop {segment} {index}\n')
|
||||
|
||||
def write_goto(self, label):
|
||||
self.my_vm.write(f'goto L{label}\n')
|
||||
print(f'goto L{label}')
|
||||
|
||||
def write_if(self, label):
|
||||
self.write_arithmetic('~')
|
||||
self.my_vm.write(f'if-goto L{label}\n')
|
||||
print(f'if-goto L{label}')
|
||||
|
||||
def write_call(self, label, num_args):
|
||||
self.my_vm.write(f'call {label} {num_args}\n')
|
||||
print(f'call {label} {num_args}')
|
||||
|
||||
def write_function(self, label, num_locals):
|
||||
self.my_vm.write(f'function {label} {num_locals}\n')
|
||||
print(f'function {label} {num_locals}')
|
||||
|
||||
def write_return(self, func_type):
|
||||
if func_type == 'void':
|
||||
self.write_push('constant', '0')
|
||||
self.my_vm.write('return\n')
|
||||
print(f'return')
|
||||
|
||||
def close_vm_file(self):
|
||||
self.my_vm.close()
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Sys.jack
|
||||
|
||||
/**
|
||||
* A library that supports various program execution services.
|
||||
*/
|
||||
class Sys {
|
||||
|
||||
/** Performs all the initializations required by the OS. */
|
||||
function void init() {
|
||||
do Memory.init();
|
||||
do Math.init();
|
||||
do Output.init();
|
||||
do Screen.init();
|
||||
do Keyboard.init();
|
||||
do Main.main();
|
||||
do Sys.halt();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Halts the program execution. */
|
||||
function void halt() {
|
||||
while(true){
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Waits approximately duration milliseconds and returns. */
|
||||
function void wait(int duration) {
|
||||
var int i;
|
||||
while (duration > 0){
|
||||
let i = 100;
|
||||
while(i > 0){
|
||||
let i = i -1;
|
||||
}
|
||||
let duration = duration - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given error code in the form "ERR<errorCode>",
|
||||
* and halts the program's execution. */
|
||||
function void error(int errorCode) {
|
||||
var String s;
|
||||
let s = String.new(3);
|
||||
do s.setInt(errorCode);
|
||||
do Output.printString("ERR");
|
||||
do Output.printString(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/SysTest/Main.jack
|
||||
|
||||
/** Test program for the OS Sys class. */
|
||||
class Main {
|
||||
|
||||
/** Tests the wait method of the Sys class. */
|
||||
function void main() {
|
||||
var char key;
|
||||
|
||||
do Output.printString("Wait test:");
|
||||
do Output.println();
|
||||
do Output.printString("Press any key. After 2 seconds, another message will be printed:");
|
||||
|
||||
while (key = 0) {
|
||||
let key = Keyboard.keyPressed();
|
||||
}
|
||||
while (~(key = 0)) {
|
||||
let key = Keyboard.keyPressed();
|
||||
}
|
||||
|
||||
do Sys.wait(2000);
|
||||
|
||||
do Output.println();
|
||||
do Output.printString("Time is up. Make sure that 2 seconds elapsed.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+281
@@ -0,0 +1,281 @@
|
||||
function Main.main 1
|
||||
push constant 10
|
||||
call String.new 1
|
||||
push constant 87
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 64
|
||||
call String.new 1
|
||||
push constant 80
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 121
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 107
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 121
|
||||
call String.appendChar 2
|
||||
push constant 46
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 65
|
||||
call String.appendChar 2
|
||||
push constant 102
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 44
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 109
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 103
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 119
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 98
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
label L0
|
||||
push local 0
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L1
|
||||
call Keyboard.keyPressed 0
|
||||
pop local 0
|
||||
goto L0
|
||||
label L1
|
||||
label L2
|
||||
push local 0
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
not
|
||||
if-goto L3
|
||||
call Keyboard.keyPressed 0
|
||||
pop local 0
|
||||
goto L2
|
||||
label L3
|
||||
push constant 2000
|
||||
call Sys.wait 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 45
|
||||
call String.new 1
|
||||
push constant 84
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 109
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 46
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 77
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 107
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 46
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Sys.jack
|
||||
|
||||
/**
|
||||
* A library that supports various program execution services.
|
||||
*/
|
||||
class Sys {
|
||||
|
||||
/** Performs all the initializations required by the OS. */
|
||||
function void init() {
|
||||
do Math.init();
|
||||
do Keyboard.init();
|
||||
do Memory.init();
|
||||
do Output.init();
|
||||
do Screen.init();
|
||||
do Main.main();
|
||||
do Sys.halt();
|
||||
}
|
||||
|
||||
/** Halts the program execution. */
|
||||
function void halt() {
|
||||
while(true){
|
||||
}
|
||||
}
|
||||
|
||||
/** Waits approximately duration milliseconds and returns. */
|
||||
function void wait(int duration) {
|
||||
var int i;
|
||||
while (duration > 0){
|
||||
let i = 100;
|
||||
while(i > 0){
|
||||
let i = i -1;
|
||||
}
|
||||
let duration = duration - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given error code in the form "ERR<errorCode>",
|
||||
* and halts the program's execution. */
|
||||
function void error(int errorCode) {
|
||||
var String s;
|
||||
let s = String.new(3);
|
||||
do s.setInt(errorCode);
|
||||
do Output.printString("ERR");
|
||||
do Output.printString(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+75
@@ -0,0 +1,75 @@
|
||||
function Sys.init 0
|
||||
call Math.init 0
|
||||
pop temp 0
|
||||
call Keyboard.init 0
|
||||
pop temp 0
|
||||
call Memory.init 0
|
||||
pop temp 0
|
||||
call Output.init 0
|
||||
pop temp 0
|
||||
call Screen.init 0
|
||||
pop temp 0
|
||||
call Main.main 0
|
||||
pop temp 0
|
||||
call Sys.halt 0
|
||||
pop temp 0
|
||||
function Sys.halt 0
|
||||
label L0
|
||||
push constant 1
|
||||
neg
|
||||
not
|
||||
if-goto L1
|
||||
goto L0
|
||||
label L1
|
||||
function Sys.wait 1
|
||||
label L2
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L3
|
||||
push constant 100
|
||||
pop local 0
|
||||
label L4
|
||||
push local 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L5
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 0
|
||||
goto L4
|
||||
label L5
|
||||
push argument 0
|
||||
push constant 1
|
||||
sub
|
||||
pop argument 0
|
||||
goto L2
|
||||
label L3
|
||||
push constant 0
|
||||
return
|
||||
function Sys.error 1
|
||||
push constant 3
|
||||
call String.new 1
|
||||
pop local 0
|
||||
push local 0
|
||||
push argument 0
|
||||
call String.setInt 2
|
||||
pop temp 0
|
||||
push constant 3
|
||||
call String.new 1
|
||||
push constant 69
|
||||
call String.appendChar 2
|
||||
push constant 82
|
||||
call String.appendChar 2
|
||||
push constant 82
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+132
@@ -0,0 +1,132 @@
|
||||
class Main{
|
||||
static Array mem;
|
||||
|
||||
|
||||
/** Initializes the screen, and locates the cursor at the screen's top-left. */
|
||||
function void test_init() {
|
||||
let mem = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
function void main(){
|
||||
var String s;
|
||||
var int i;
|
||||
let s = String.new(10);
|
||||
do Main.test_init();
|
||||
let s = Main.readLine("String: ");
|
||||
let i = Main.readInt("INT: ");
|
||||
do Output.printString(s);
|
||||
do Output.printInt(i);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
function char keyPressed(){
|
||||
return mem[24576];
|
||||
}
|
||||
|
||||
function int readInt_stolen(String message){
|
||||
var starting a;
|
||||
var int b;
|
||||
let a = Main.readLine_stolen(message);
|
||||
let b = String.intValue(a);
|
||||
do String.dispose(a);
|
||||
return b;
|
||||
}
|
||||
function string readLine_stolen(String message){
|
||||
var char a, b ,c;
|
||||
var String d;
|
||||
var bool e;
|
||||
let d = String.new(80);
|
||||
do Output.printString(message);
|
||||
let b = String.newLine();
|
||||
let c = String.backSpace();
|
||||
while (~e){
|
||||
let a = Main.readChar();
|
||||
let e = a = b;
|
||||
if (~e){
|
||||
if (a = c){
|
||||
do d.eraseLastChar();
|
||||
}
|
||||
else{
|
||||
do d.appendChar(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
/**
|
||||
* Displays the message on the screen, reads from the keyboard the entered
|
||||
* text until a newline character is detected, echoes the text to the screen,
|
||||
* and returns its value. Also handles user backspaces.
|
||||
*/
|
||||
function String readLine(String message){
|
||||
var String s, b;
|
||||
var char c;
|
||||
let s = String.new(100);
|
||||
do Output.printString(message);
|
||||
while (true){
|
||||
let c = Main.readChar();
|
||||
if (c = 128){
|
||||
return s;
|
||||
}
|
||||
else{
|
||||
if (c = 129){
|
||||
do s.eraseLastChar();
|
||||
}
|
||||
else{
|
||||
do s.appendChar(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Waits until a key is pressed on the keyboard and released,
|
||||
* then echoes the key to the screen, and returns the character
|
||||
* of the pressed key.
|
||||
*/
|
||||
function char readChar(){
|
||||
var char a, b;
|
||||
do Output.printChar(0);
|
||||
while ((b = 0) | (a > 0)){
|
||||
let a = Main.keyPressed();
|
||||
if (a > 0){
|
||||
let b = a;
|
||||
}
|
||||
}
|
||||
do Output.printChar(String.backSpace());
|
||||
do Output.printChar(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Displays the message on the screen, reads from the keyboard the entered
|
||||
* text until a newline character is detected, echoes the text to the screen,
|
||||
* and returns its integer value (until the first non-digit character in the
|
||||
* entered text is detected). Also handles user backspaces.
|
||||
*/
|
||||
function int readInt(String message) {
|
||||
var String s;
|
||||
var char c;
|
||||
let s = String.new(100);
|
||||
do Output.printString(message);
|
||||
while (true){
|
||||
let c = Main.readChar(c);
|
||||
if (c = 128){
|
||||
return s.intValue();
|
||||
}
|
||||
else{
|
||||
if (c = 129){
|
||||
let s = s.eraseLastChar();
|
||||
}
|
||||
else{
|
||||
if ((c > 47) & (c < 57)){
|
||||
let s = s.appendChar(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+341
@@ -0,0 +1,341 @@
|
||||
class Main {
|
||||
|
||||
static int division_tmp;
|
||||
static Array mem;
|
||||
static Array st;
|
||||
static int f;
|
||||
static boolean color;
|
||||
|
||||
/** Initializes the library. */
|
||||
function void init_test() {
|
||||
var int a;
|
||||
let st = Array.new(16);
|
||||
let st[0] = 1;
|
||||
while (a < 15){
|
||||
let a = a + 1;
|
||||
let st[a] = st[a - 1] + st[a - 1];
|
||||
}
|
||||
let color = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
function void main(){
|
||||
do Main.init_test();
|
||||
do Main.test_drawPixel(256,128);
|
||||
do Main.test_drawPixel(255,128);
|
||||
do Main.test_drawPixel(257,128);
|
||||
do Main.test_changeColor(0);
|
||||
do Main.test_drawPixel(256,128);
|
||||
return;
|
||||
}
|
||||
function void test_changeColor(boolean x){
|
||||
let color = x;
|
||||
return;
|
||||
}
|
||||
function void test_clearScreen(){
|
||||
var int a;
|
||||
let a = 16384;
|
||||
while (a < 24575){
|
||||
let mem[a] = 0;
|
||||
let a = a + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
function void test_drawRectangle(int x1, int y1, int x2, int y2){
|
||||
var int a, tmp;
|
||||
if (x1 > x2){
|
||||
let tmp = x1;
|
||||
let x1 = x2;
|
||||
let x2 = tmp;
|
||||
}
|
||||
if (y1 > y2){
|
||||
let tmp = y1;
|
||||
let y1 = y2;
|
||||
let y2 = tmp;
|
||||
}
|
||||
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
|
||||
do Sys.error(8);
|
||||
}
|
||||
while(a < y2){
|
||||
do Screen.drawLine(x1, y1 + a, x2, y1 + a);
|
||||
let a = a + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
function void test_drawCicle(int x, int y, int r){
|
||||
var int dy, dx, tmp;
|
||||
if(r > 181){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let dy = - r;
|
||||
while (dy < r){
|
||||
let tmp = Math.sqrt((r * r) - (dy * dy));
|
||||
do Screen.drawLine(x - tmp, y + dy, x + tmp, y + dy);
|
||||
let dy = dy + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
function void test_drawLine_optimize(int x1, int y1, int x2, int y2){
|
||||
var int diff, dx, dy, a, b, tmp;
|
||||
if (x1 > x2){
|
||||
let tmp = x1;
|
||||
let x1 = x2;
|
||||
let x2 = tmp;
|
||||
}
|
||||
if (y1 > y2){
|
||||
let tmp = y1;
|
||||
let y1 = y2;
|
||||
let y2 = tmp;
|
||||
}
|
||||
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
|
||||
do Sys.error(8);
|
||||
}
|
||||
let dx = x2 - x1;
|
||||
let dy = y2 - y1;
|
||||
if (dx = 0){
|
||||
while(~(b > dy)){
|
||||
do Screen.drawPixel(x1, y1 + b);
|
||||
let b = b + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (dy = 0){
|
||||
while(~(a > dx)){
|
||||
do Screen.drawPixel(x1 + a, y1);
|
||||
let a = a + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
while ((~(a > dx)) & (~(b > dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a + 1;
|
||||
let diff = diff + dy;
|
||||
}
|
||||
else{
|
||||
let b = b + 1;
|
||||
let diff = diff - dx;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function void test_drawPixel(int x, int y) {
|
||||
var int value, address, bit, mem_block;
|
||||
if ((x > 511) | (x < 0) | (y > 255) | (y < 0)){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let mem_block = x / 16;
|
||||
let address = (32 * y) + mem_block + 16384;
|
||||
let value = mem[address];
|
||||
let bit = x - (mem_block * 16);
|
||||
if (color = 1){
|
||||
let mem[address] = st[bit] | value;
|
||||
}
|
||||
else{
|
||||
let mem[address] = (~st[bit])& value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
function int test_multiply(int x, int y){
|
||||
var int sum, temp, y_comp, i, neg;
|
||||
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
|
||||
let x = Math.abs(x);
|
||||
let y = Math.abs(y);
|
||||
if (x < y){
|
||||
let temp = x;
|
||||
let x = y;
|
||||
let y = temp;
|
||||
}
|
||||
if (y = 1){
|
||||
if(neg){
|
||||
return -x;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
while((y_comp - 1) < (y - 1)){
|
||||
if ((st[i] & y) > 0) {
|
||||
let sum = sum + x;
|
||||
let y_comp = y_comp + st[i];
|
||||
}
|
||||
let x = x + x;
|
||||
let i = i + 1;
|
||||
}
|
||||
if(neg){
|
||||
let sum = -sum;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
function int test_max(int x, int y){
|
||||
if (x > y){
|
||||
return x;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
function int test_min(int x, int y){
|
||||
if (x < y){
|
||||
return x;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
function int test_sqrt(int x) {
|
||||
var int j, b, d, y;
|
||||
if (x < 0){
|
||||
do Sys.error(4);
|
||||
}
|
||||
let j = 7;
|
||||
while (j > -1){
|
||||
let d = y + st[j];
|
||||
let b = Main.test_multiply(d,d);
|
||||
if ((~(b > x)) & (b > 0)){
|
||||
let y = d;
|
||||
}
|
||||
let j = j - 1;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
function int test_divide(int x, int y) {
|
||||
var int q, neg;
|
||||
if (f = 0){
|
||||
let division_tmp = 0;
|
||||
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
|
||||
let x = Math.abs(x);
|
||||
let y = Math.abs(y);
|
||||
if (y = 0){
|
||||
do Sys.error(3);
|
||||
}
|
||||
let f = 1;
|
||||
}
|
||||
if ((y > x) | (y < 0)){
|
||||
return 0;
|
||||
}
|
||||
let q = test_divide(x, y + y);
|
||||
let f = 0;
|
||||
let q = Math.abs(q);
|
||||
if ((q & 1) = 1){
|
||||
let division_tmp = division_tmp + y + y;
|
||||
}
|
||||
if (x - division_tmp < y){
|
||||
if (neg){
|
||||
return -(q + q);
|
||||
}
|
||||
return q + q;
|
||||
}
|
||||
else{
|
||||
if (neg){
|
||||
return -(q + q + 1);
|
||||
}
|
||||
return q + q + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function int test_abs(int x) {
|
||||
if (x > 0){
|
||||
return x;
|
||||
}
|
||||
return -x;
|
||||
}
|
||||
|
||||
function int test_peek(int x){
|
||||
return mem[x];
|
||||
}
|
||||
|
||||
function void test_poke(int x, int y){
|
||||
let mem[x] = y;
|
||||
return;
|
||||
}
|
||||
|
||||
function int test_dealloc_stolen(Array x){
|
||||
var int obj_add,b;
|
||||
let obj_add = x - 2;
|
||||
let b = obj_add[1];
|
||||
if (b[0] = 0){
|
||||
let obj_add[0] = obj_add[1] - obj_add -2;
|
||||
}
|
||||
else{
|
||||
let obj_add[0] = obj_add[1] - obj_add + b[0];
|
||||
if (b[1] = b +2){
|
||||
let obj_add[1] = obj_add + 2;
|
||||
}
|
||||
else{
|
||||
let obj_add[1] = b[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function void test_dealloc(Array o){
|
||||
var Array current_block;
|
||||
let current_block = 2048;
|
||||
let o[1]= current_block[1];
|
||||
let current_block[1] = o;
|
||||
}
|
||||
|
||||
function int test_alloc(int size){
|
||||
var Array current_block;
|
||||
var int tmp;
|
||||
let current_block = 2048;
|
||||
if (size < 0){
|
||||
do Sys.error(5);
|
||||
}
|
||||
if (size = 0){
|
||||
let size = 1;
|
||||
}
|
||||
while (current_block[0] < (size + 2)) {
|
||||
let current_block = current_block[1];
|
||||
}
|
||||
let current_block[0] = current_block[0] - size - 2;
|
||||
let current_block = current_block + current_block[0] + 2;
|
||||
let current_block[0] = size;
|
||||
return current_block + 2;
|
||||
}
|
||||
|
||||
function int test_alloc_stolen(int x){
|
||||
var Array curret_block, next_block;
|
||||
if (x < 0){
|
||||
do Sys.error(5);
|
||||
}
|
||||
if (x = 0){
|
||||
let x = 1;
|
||||
}
|
||||
let curret_block = 2048;
|
||||
let curret_block[0] = 14334;
|
||||
let curret_block[1] = 2050;
|
||||
while ((curret_block < 16383) & (curret_block[0] < x)){
|
||||
let next_block = curret_block[1];
|
||||
if ((curret_block[0] = 0) | (next_block > 16382) | (next_block[0] = 0)){ // this sends directly out of while
|
||||
let curret_block = next_block;
|
||||
}
|
||||
else {
|
||||
let curret_block[0] = curret_block[1] - curret_block + next_block[0]; // cb size =
|
||||
if (next_block[1] = next_block + 2){
|
||||
let curret_block[1] = curret_block + 2;
|
||||
}
|
||||
else{
|
||||
let curret_block[1] = next_block[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((curret_block + x) > 16379){
|
||||
do Sys.error(6);
|
||||
}
|
||||
if (curret_block[0] > (x + 2)){ // if current block fills the desired size perfectly
|
||||
let curret_block[x + 2] = curret_block[0] - x -2;
|
||||
if (curret_block[1] = curret_block + 2){
|
||||
let curret_block[x + 3] = curret_block + x + 4;
|
||||
}
|
||||
else{
|
||||
let curret_block[x + 3] = curret_block[1];
|
||||
}
|
||||
}
|
||||
let curret_block[0] = 0;
|
||||
return (curret_block + 2);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Executable
+280
@@ -0,0 +1,280 @@
|
||||
class Main {
|
||||
|
||||
|
||||
static Array charMaps;
|
||||
static int address;
|
||||
static bool half;
|
||||
|
||||
|
||||
/** Initializes the screen, and locates the cursor at the screen's top-left. */
|
||||
function void test_init() {
|
||||
do Main.initMap();
|
||||
do Main.moveCursor(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
function void main(){tInt(i);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Returns the character map (array of size 11) of the given character.
|
||||
// If the given character is invalid or non-printable, returns the
|
||||
// character map of a black square.
|
||||
function Array getMap(char c) {
|
||||
if ((c < 32) | (c > 126)) {
|
||||
let c = 0;
|
||||
}
|
||||
return charMaps[c];
|
||||
}
|
||||
|
||||
/** Moves the cursor to the j-th column of the i-th row,
|
||||
* and erases the character displayed there. */
|
||||
function void moveCursor(int i, int j) {
|
||||
var int count, display;
|
||||
var Array r, char;
|
||||
if (j = 0){
|
||||
let half = true;
|
||||
}
|
||||
else{
|
||||
let half = (j / 2) * 2 = j; // chetno true, 1vaa chast
|
||||
}
|
||||
let address = (352 * i) + (j / 2) + 16384;
|
||||
let char = Main.getMap(32);
|
||||
|
||||
while (count < 11){
|
||||
if (half){
|
||||
let display = r[address] & (-256);
|
||||
let r[address] = char[count] | display;
|
||||
}
|
||||
else{
|
||||
let display = r[address] & 255;
|
||||
let r[address] = (char[count]*256) | display;
|
||||
}
|
||||
let count = count + 1;
|
||||
let address = address + 32;
|
||||
}
|
||||
let address = address - 352;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given character at the cursor location,
|
||||
* and advances the cursor one column forward. */
|
||||
function void printChar(char c) {
|
||||
var Array char, r;
|
||||
var int count, display;
|
||||
let char = Main.getMap(c);
|
||||
while (count < 11){
|
||||
if (half){
|
||||
let display = r[address] & (-256);
|
||||
let r[address] = char[count] | display;
|
||||
}
|
||||
else{
|
||||
let display = r[address] & 255;
|
||||
let r[address] = (char[count]*256) | display;
|
||||
}
|
||||
let count = count + 1;
|
||||
let address = address + 32;
|
||||
}
|
||||
|
||||
if (half){
|
||||
let address = address - 352;
|
||||
let half = false;
|
||||
}
|
||||
else{
|
||||
if (address > 24480){
|
||||
let address = 16384;
|
||||
let half = true;
|
||||
}
|
||||
else{
|
||||
let address = address - 351;
|
||||
let half = true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** displays the given string starting at the cursor location,
|
||||
* and advances the cursor appropriately. */
|
||||
function void printString(String s) {
|
||||
var int i, length;
|
||||
let length = s.length();
|
||||
while (i < length){
|
||||
do Main.printChar(s[i+2]);
|
||||
let i = i + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given integer starting at the cursor location,
|
||||
* and advances the cursor appropriately. */
|
||||
function void printInt(int i) {
|
||||
var String s;
|
||||
let s = String.new(6);
|
||||
do s.setInt(i);
|
||||
do Main.printString(s);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Advances the cursor to the beginning of the next line. */
|
||||
function void println() {
|
||||
var int row;
|
||||
let row = (((address - 16384) / 32)/11) + 1;
|
||||
if (row > 32){
|
||||
let row = 0;
|
||||
}
|
||||
do Main.moveCursor(row, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the cursor one column back. */
|
||||
function void backSpace() {
|
||||
if (address = 16384){
|
||||
let address = 24191;
|
||||
let half = true;
|
||||
return;
|
||||
}
|
||||
if (half){
|
||||
|
||||
let address = address - 1;
|
||||
let half = false;
|
||||
}
|
||||
else{
|
||||
let half = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Initializes the character map array
|
||||
function void initMap() {
|
||||
var int i;
|
||||
|
||||
let charMaps = Array.new(127);
|
||||
|
||||
// Black square, used for displaying non-printable characters.
|
||||
do Main.create(0,63,63,63,63,63,63,63,63,63,0,0);
|
||||
// Assigns the bitmap for each character in the charachter set.
|
||||
// The first parameter is the character index, the next 11 numbers
|
||||
// are the values of each row in the frame that represents this character.
|
||||
do Main.create(32,0,0,0,0,0,0,0,0,0,0,0); //
|
||||
do Main.create(33,12,30,30,30,12,12,0,12,12,0,0); // !
|
||||
do Main.create(34,54,54,20,0,0,0,0,0,0,0,0); // "
|
||||
do Main.create(35,0,18,18,63,18,18,63,18,18,0,0); // #
|
||||
do Main.create(36,12,30,51,3,30,48,51,30,12,12,0); // $
|
||||
do Main.create(37,0,0,35,51,24,12,6,51,49,0,0); // %
|
||||
do Main.create(38,12,30,30,12,54,27,27,27,54,0,0); // &
|
||||
do Main.create(39,12,12,6,0,0,0,0,0,0,0,0); // '
|
||||
do Main.create(40,24,12,6,6,6,6,6,12,24,0,0); // (
|
||||
do Main.create(41,6,12,24,24,24,24,24,12,6,0,0); // )
|
||||
do Main.create(42,0,0,0,51,30,63,30,51,0,0,0); // *
|
||||
do Main.create(43,0,0,0,12,12,63,12,12,0,0,0); // +
|
||||
do Main.create(44,0,0,0,0,0,0,0,12,12,6,0); // ,
|
||||
do Main.create(45,0,0,0,0,0,63,0,0,0,0,0); // -
|
||||
do Main.create(46,0,0,0,0,0,0,0,12,12,0,0); // .
|
||||
do Main.create(47,0,0,32,48,24,12,6,3,1,0,0); // /
|
||||
do Main.create(48,12,30,51,51,51,51,51,30,12,0,0); // 0
|
||||
do Main.create(49,12,14,15,12,12,12,12,12,63,0,0); // 1
|
||||
do Main.create(50,30,51,48,24,12,6,3,51,63,0,0); // 2
|
||||
do Main.create(51,30,51,48,48,28,48,48,51,30,0,0); // 3
|
||||
do Main.create(52,16,24,28,26,25,63,24,24,60,0,0); // 4
|
||||
do Main.create(53,63,3,3,31,48,48,48,51,30,0,0); // 5
|
||||
do Main.create(54,28,6,3,3,31,51,51,51,30,0,0); // 6
|
||||
do Main.create(55,63,49,48,48,24,12,12,12,12,0,0); // 7
|
||||
do Main.create(56,30,51,51,51,30,51,51,51,30,0,0); // 8
|
||||
do Main.create(57,30,51,51,51,62,48,48,24,14,0,0); // 9
|
||||
do Main.create(58,0,0,12,12,0,0,12,12,0,0,0); // :
|
||||
do Main.create(59,0,0,12,12,0,0,12,12,6,0,0); // ;
|
||||
do Main.create(60,0,0,24,12,6,3,6,12,24,0,0); // <
|
||||
do Main.create(61,0,0,0,63,0,0,63,0,0,0,0); // =
|
||||
do Main.create(62,0,0,3,6,12,24,12,6,3,0,0); // >
|
||||
do Main.create(64,30,51,51,59,59,59,27,3,30,0,0); // @
|
||||
do Main.create(63,30,51,51,24,12,12,0,12,12,0,0); // ?
|
||||
do Main.create(65,12,30,51,51,63,51,51,51,51,0,0); // A
|
||||
do Main.create(66,31,51,51,51,31,51,51,51,31,0,0); // B
|
||||
do Main.create(67,28,54,35,3,3,3,35,54,28,0,0); // C
|
||||
do Main.create(68,15,27,51,51,51,51,51,27,15,0,0); // D
|
||||
do Main.create(69,63,51,35,11,15,11,35,51,63,0,0); // E
|
||||
do Main.create(70,63,51,35,11,15,11,3,3,3,0,0); // F
|
||||
do Main.create(71,28,54,35,3,59,51,51,54,44,0,0); // G
|
||||
do Main.create(72,51,51,51,51,63,51,51,51,51,0,0); // H
|
||||
do Main.create(73,30,12,12,12,12,12,12,12,30,0,0); // I
|
||||
do Main.create(74,60,24,24,24,24,24,27,27,14,0,0); // J
|
||||
do Main.create(75,51,51,51,27,15,27,51,51,51,0,0); // K
|
||||
do Main.create(76,3,3,3,3,3,3,35,51,63,0,0); // L
|
||||
do Main.create(77,33,51,63,63,51,51,51,51,51,0,0); // M
|
||||
do Main.create(78,51,51,55,55,63,59,59,51,51,0,0); // N
|
||||
do Main.create(79,30,51,51,51,51,51,51,51,30,0,0); // O
|
||||
do Main.create(80,31,51,51,51,31,3,3,3,3,0,0); // P
|
||||
do Main.create(81,30,51,51,51,51,51,63,59,30,48,0);// Q
|
||||
do Main.create(82,31,51,51,51,31,27,51,51,51,0,0); // R
|
||||
do Main.create(83,30,51,51,6,28,48,51,51,30,0,0); // S
|
||||
do Main.create(84,63,63,45,12,12,12,12,12,30,0,0); // T
|
||||
do Main.create(85,51,51,51,51,51,51,51,51,30,0,0); // U
|
||||
do Main.create(86,51,51,51,51,51,30,30,12,12,0,0); // V
|
||||
do Main.create(87,51,51,51,51,51,63,63,63,18,0,0); // W
|
||||
do Main.create(88,51,51,30,30,12,30,30,51,51,0,0); // X
|
||||
do Main.create(89,51,51,51,51,30,12,12,12,30,0,0); // Y
|
||||
do Main.create(90,63,51,49,24,12,6,35,51,63,0,0); // Z
|
||||
|
||||
do Main.create(91,30,6,6,6,6,6,6,6,30,0,0); // [
|
||||
do Main.create(92,0,0,1,3,6,12,24,48,32,0,0); // \
|
||||
do Main.create(93,30,24,24,24,24,24,24,24,30,0,0); // ]
|
||||
do Main.create(94,8,28,54,0,0,0,0,0,0,0,0); // ^
|
||||
do Main.create(95,0,0,0,0,0,0,0,0,0,63,0); // _
|
||||
do Main.create(96,6,12,24,0,0,0,0,0,0,0,0); // `
|
||||
do Main.create(97,0,0,0,14,24,30,27,27,54,0,0); // a
|
||||
do Main.create(98,3,3,3,15,27,51,51,51,30,0,0); // b
|
||||
do Main.create(99,0,0,0,30,51,3,3,51,30,0,0); // c
|
||||
do Main.create(100,48,48,48,60,54,51,51,51,30,0,0); // d
|
||||
do Main.create(101,0,0,0,30,51,63,3,51,30,0,0); // e
|
||||
do Main.create(102,28,54,38,6,15,6,6,6,15,0,0); // f
|
||||
do Main.create(103,0,0,30,51,51,51,62,48,51,30,0); // g
|
||||
do Main.create(104,3,3,3,27,55,51,51,51,51,0,0); // h
|
||||
do Main.create(105,12,12,0,14,12,12,12,12,30,0,0); // i
|
||||
do Main.create(106,48,48,0,56,48,48,48,48,51,30,0); // j
|
||||
do Main.create(107,3,3,3,51,27,15,15,27,51,0,0); // k
|
||||
do Main.create(108,14,12,12,12,12,12,12,12,30,0,0); // l
|
||||
do Main.create(109,0,0,0,29,63,43,43,43,43,0,0); // m
|
||||
do Main.create(110,0,0,0,29,51,51,51,51,51,0,0); // n
|
||||
do Main.create(111,0,0,0,30,51,51,51,51,30,0,0); // o
|
||||
do Main.create(112,0,0,0,30,51,51,51,31,3,3,0); // p
|
||||
do Main.create(113,0,0,0,30,51,51,51,62,48,48,0); // q
|
||||
do Main.create(114,0,0,0,29,55,51,3,3,7,0,0); // r
|
||||
do Main.create(115,0,0,0,30,51,6,24,51,30,0,0); // s
|
||||
do Main.create(116,4,6,6,15,6,6,6,54,28,0,0); // t
|
||||
do Main.create(117,0,0,0,27,27,27,27,27,54,0,0); // u
|
||||
do Main.create(118,0,0,0,51,51,51,51,30,12,0,0); // v
|
||||
do Main.create(119,0,0,0,51,51,51,63,63,18,0,0); // w
|
||||
do Main.create(120,0,0,0,51,30,12,12,30,51,0,0); // x
|
||||
do Main.create(121,0,0,0,51,51,51,62,48,24,15,0); // y
|
||||
do Main.create(122,0,0,0,63,27,12,6,51,63,0,0); // z
|
||||
do Main.create(123,56,12,12,12,7,12,12,12,56,0,0); // {
|
||||
do Main.create(124,12,12,12,12,12,12,12,12,12,0,0); // |
|
||||
do Main.create(125,7,12,12,12,56,12,12,12,7,0,0); // }
|
||||
do Main.create(126,38,45,25,0,0,0,0,0,0,0,0); // ~
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Creates the character map array of the given character index, using the given values.
|
||||
function void create(int index, int a, int b, int c, int d, int e,
|
||||
int f, int g, int h, int i, int j, int k) {
|
||||
var Array map;
|
||||
|
||||
let map = Array.new(11);
|
||||
let charMaps[index] = map;
|
||||
|
||||
let map[0] = a;
|
||||
let map[1] = b;
|
||||
let map[2] = c;
|
||||
let map[3] = d;
|
||||
let map[4] = e;
|
||||
let map[5] = f;
|
||||
let map[6] = g;
|
||||
let map[7] = h;
|
||||
let map[8] = i;
|
||||
let map[9] = j;
|
||||
let map[10] = k;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+148
@@ -0,0 +1,148 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/String.jack
|
||||
|
||||
/**
|
||||
* Represents character strings. In addition for constructing and disposing
|
||||
* strings, the class features methods for getting and setting individual
|
||||
* characters of the string, for erasing the string's last character,
|
||||
* for appending a character to the string's end, and more typical
|
||||
* string-oriented operations.
|
||||
*/
|
||||
class String {
|
||||
field Array str;
|
||||
field int length;
|
||||
static bool neg;
|
||||
|
||||
/** constructs a new empty string with a maximum length of maxLength
|
||||
* and initial length of 0. */
|
||||
constructor String new(int maxLength) {
|
||||
if (maxLength > 0){
|
||||
let str = Array.new(maxLength);
|
||||
}
|
||||
let length = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Disposes this string. */
|
||||
method void dispose() {
|
||||
if(length > 0){
|
||||
do str.dispose();
|
||||
}
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the current length of this string. */
|
||||
method int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Returns the character at the j-th location of this string. */
|
||||
method char charAt(int j) {
|
||||
if(j > length){
|
||||
do Sys.error(7);
|
||||
}
|
||||
return str[j];
|
||||
}
|
||||
|
||||
/** Sets the character at the j-th location of this string to c. */
|
||||
method void setCharAt(int j, char c) {
|
||||
if(j > length){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let str[j] = c;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Appends c to this string's end and returns this string. */
|
||||
method String appendChar(char c) {
|
||||
let str[length] = c;
|
||||
let length = length + 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Erases the last character from this string. */
|
||||
method void eraseLastChar() {
|
||||
let str[length] = 0;
|
||||
let length = length - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the integer value of this string,
|
||||
* until a non-digit character is detected. */
|
||||
method int intValue() {
|
||||
var int d, sum, i;
|
||||
var bool f;
|
||||
while(i < length){
|
||||
let d = str[i]; // kak da go zavyrtq v realen int
|
||||
if ((d > 47) & (d < 58)){
|
||||
let sum = (sum * 10) + (d - 48);
|
||||
}
|
||||
else{
|
||||
if((i = 0) & (d = 45)){
|
||||
let f = true;
|
||||
}
|
||||
else{
|
||||
let i = length;
|
||||
}
|
||||
}
|
||||
let i = i + 1;
|
||||
}
|
||||
if (f){
|
||||
return -sum;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/** Sets this string to hold a representation of the given value. */
|
||||
method void setInt(int val) {
|
||||
var int lastDigit, a,i;
|
||||
var char c;
|
||||
if(val < 0){
|
||||
let neg = true;
|
||||
let val = -val;
|
||||
}
|
||||
let a = val / 10;
|
||||
let lastDigit = val - (a * 10);
|
||||
let i = 48;
|
||||
while (i < 58){
|
||||
if (i = (48 + lastDigit)){
|
||||
let c = i;
|
||||
let i = 59;
|
||||
}
|
||||
let i = i + 1;
|
||||
}
|
||||
if (val < 10){
|
||||
let length = 0;
|
||||
if (neg){
|
||||
let neg = false;
|
||||
do this.appendChar(45);
|
||||
}
|
||||
|
||||
do this.appendChar(c);
|
||||
return;
|
||||
}
|
||||
else{
|
||||
do this.setInt(a);
|
||||
do this.appendChar(c);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the new line character. */
|
||||
function char newLine() {
|
||||
return 128;
|
||||
}
|
||||
|
||||
/** Returns the backspace character. */
|
||||
function char backSpace() {
|
||||
return 129;
|
||||
}
|
||||
|
||||
/** Returns the double quote (") character. */
|
||||
function char doubleQuote() {
|
||||
return 34;
|
||||
}
|
||||
}
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Array.jack
|
||||
|
||||
/**
|
||||
* Represents an array.
|
||||
* In the Jack language, arrays are instances of the Array class.
|
||||
* Once declared, the array entries can be accessed using the usual
|
||||
* syntax arr[i]. Each array entry can hold a primitive data type as
|
||||
* well as any object type. Different array entries can have different
|
||||
* data types.
|
||||
*/
|
||||
class Array {
|
||||
|
||||
/** Constructs a new Array of the given size. */
|
||||
function Array new(int size) {
|
||||
if(size < 0){
|
||||
do Sys.error(7);
|
||||
}
|
||||
return Memory.alloc(size);
|
||||
}
|
||||
|
||||
/** Disposes this array. */
|
||||
method void dispose() {
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
function Array.new 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L0
|
||||
push constant 7
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L1
|
||||
label L0
|
||||
label L1
|
||||
push argument 0
|
||||
call Memory.alloc 1
|
||||
return
|
||||
function Array.dispose 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push pointer 0
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+350
@@ -0,0 +1,350 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from tokenizer import Tokenizer
|
||||
from vmwriter import VMWriter
|
||||
from symbol_table import SymbolTable
|
||||
|
||||
|
||||
# TODO add names to variables when you call for them, aka current_vm_append(thingtobeappended=blablac)
|
||||
|
||||
class CompilationEngine:
|
||||
def __init__(self, tokenizer, full_path_vm):
|
||||
self.string = self.sub_type = self.class_name = self.function_type = ''
|
||||
self.tab = self.recursion_index = 0
|
||||
self.tokenizer = tokenizer
|
||||
self.sym_table = []
|
||||
self.vmwriter = VMWriter(full_path_vm)
|
||||
self.current_vm = [] # used to reverse some of the commands, eg a+b need to be a b +
|
||||
|
||||
def search_kind_of_sym(self, current_vm):
|
||||
if self.sym_table[-1].kind_of(current_vm) is not None:
|
||||
return self.sym_table[-1].kind_of(current_vm), self.sym_table[-1].index_of(current_vm)
|
||||
for i in range(len(self.sym_table) - 2, -1,
|
||||
-1): # start from the amount of sym_tables -2 so it starts from one below the current,
|
||||
# until it is bigger than -1, walking it backwards
|
||||
if self.sym_table[i].kind_of(current_vm) in ('static', 'this'):
|
||||
return self.sym_table[i].kind_of(current_vm), self.sym_table[i].index_of(current_vm)
|
||||
|
||||
def search_type_of_sym(self, current_vm):
|
||||
for i in range(len(self.sym_table) - 1, -1, -1):
|
||||
if self.sym_table[i].type_of(current_vm) is not None:
|
||||
return self.sym_table[i].type_of(current_vm)
|
||||
|
||||
def write_token(self):
|
||||
if self.tokenizer.token_type() == 'stringConstant':
|
||||
self.string += ' ' * self.tab + '<' + self.tokenizer.token_type() + '> ' + self.tokenizer.token.strip(
|
||||
'"') + ' </' + self.tokenizer.token_type() + '>\n'
|
||||
else:
|
||||
self.string += ' ' * self.tab + '<' + self.tokenizer.token_type() + '> ' + self.tokenizer.token + ' </' \
|
||||
+ self.tokenizer.token_type() + '>\n'
|
||||
|
||||
def compile_class(self):
|
||||
self.sym_table.append(SymbolTable())
|
||||
self.tokenizer.advance() # class ->
|
||||
self.tokenizer.advance() # type ->
|
||||
self.class_name = self.tokenizer.token
|
||||
self.tokenizer.advance() # name ->
|
||||
self.tokenizer.advance() # { ->
|
||||
while self.tokenizer.token != '}':
|
||||
if self.tokenizer.token in ['static', 'field']:
|
||||
self.compile_class_var_dec()
|
||||
if self.tokenizer.token in ['constructor', 'function', 'method']:
|
||||
self.compile_subroutine()
|
||||
self.tokenizer.advance()
|
||||
self.sym_table.pop()
|
||||
self.vmwriter.close_vm_file()
|
||||
|
||||
def compile_class_var_dec(self):
|
||||
var_kind = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_type = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
while self.tokenizer.token == ',':
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
self.tokenizer.advance()
|
||||
|
||||
def compile_subroutine(self):
|
||||
self.sym_table.append(SymbolTable())
|
||||
self.sub_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine type(function|method|constructor) ->
|
||||
self.function_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine kind(int|void|etc..) ->
|
||||
sub_name = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine name ->
|
||||
self.tokenizer.advance() # ( ->
|
||||
if self.sub_type == 'method':
|
||||
self.sym_table[-1].start_subroutine('this', self.class_name)
|
||||
self.compile_parameter_list()
|
||||
self.tokenizer.advance() # { ->
|
||||
while self.tokenizer.token == 'var': # create only symbol teable entries
|
||||
self.compile_var_dec()
|
||||
if self.sub_type == 'constructor':
|
||||
self.vmwriter.write_function(f'{self.class_name}.{sub_name}', self.sym_table[-1].var_count('var'))
|
||||
self.vmwriter.write_push('constant', self.sym_table[-2].var_count('field'))
|
||||
self.vmwriter.write_call('Memory.alloc', 1)
|
||||
self.vmwriter.write_pop('pointer', 0)
|
||||
elif self.sub_type == 'method':
|
||||
self.vmwriter.write_function(f'{self.class_name}.{sub_name}', self.sym_table[-1].var_count('var'))
|
||||
self.vmwriter.write_push('argument', 0)
|
||||
self.vmwriter.write_pop('pointer', 0)
|
||||
else:
|
||||
self.vmwriter.write_function(f'{self.class_name}.{sub_name}', self.sym_table[-1].var_count('var'))
|
||||
while self.tokenizer.token != '}':
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance()
|
||||
self.sym_table.pop()
|
||||
|
||||
def compile_parameter_list(self):
|
||||
if self.tokenizer.token != ')':
|
||||
var_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # var ype ->
|
||||
var_name = self.tokenizer.token
|
||||
self.sym_table[-1].define(var_name, var_type, 'argument')
|
||||
self.tokenizer.advance() # var name ->
|
||||
while self.tokenizer.token == ',':
|
||||
self.tokenizer.advance() # , ->
|
||||
var_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # type ->
|
||||
var_name = self.tokenizer.token
|
||||
self.sym_table[-1].define(var_name, var_type, 'argument')
|
||||
self.tokenizer.advance() # name ->
|
||||
self.tokenizer.advance() # )->
|
||||
|
||||
def compile_var_dec(self):
|
||||
var_kind = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_type = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
while self.tokenizer.token == ',':
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
self.tokenizer.advance()
|
||||
|
||||
def compile_statements(self):
|
||||
while True:
|
||||
if self.tokenizer.token == 'let':
|
||||
self.compile_let()
|
||||
elif self.tokenizer.token == 'if':
|
||||
self.compile_if()
|
||||
elif self.tokenizer.token == 'while':
|
||||
self.compile_while()
|
||||
elif self.tokenizer.token == 'do':
|
||||
self.compile_do()
|
||||
elif self.tokenizer.token == 'return':
|
||||
self.compile_return()
|
||||
else:
|
||||
break
|
||||
|
||||
def compile_do(self):
|
||||
self.tokenizer.advance() # do ->
|
||||
class_name = self.tokenizer.token
|
||||
self.tokenizer.advance() # name ->
|
||||
if self.tokenizer.token == '(': # method
|
||||
self.vmwriter.write_push('pointer', 0)
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
self.vmwriter.write_call(f'{self.class_name}.{class_name}', count + 1)
|
||||
elif self.tokenizer.token == '.': # method or function
|
||||
self.tokenizer.advance() # . ->
|
||||
fname = f'{class_name}.{self.tokenizer.token}'
|
||||
sname = f'{self.search_type_of_sym(class_name)}.{self.tokenizer.token}'
|
||||
self.tokenizer.advance() # name ->
|
||||
if self.search_kind_of_sym(class_name) is not None:
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(class_name))
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
if self.search_kind_of_sym(class_name) is not None:
|
||||
self.vmwriter.write_call(f'{sname}', count + 1)
|
||||
else:
|
||||
self.vmwriter.write_call(f'{fname}', count)
|
||||
self.vmwriter.write_pop('temp', '0')
|
||||
self.tokenizer.advance() # ; ->
|
||||
|
||||
def compile_let(self):
|
||||
flag_array = 0
|
||||
self.tokenizer.advance() # let ->
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
self.tokenizer.advance() # var_name ->
|
||||
if self.tokenizer.token == '[':
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
self.tokenizer.advance() # [ ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ] ->
|
||||
flag_array = 1
|
||||
self.tokenizer.advance() # = ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ; ->
|
||||
if flag_array == 0:
|
||||
self.vmwriter.write_pop(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
else:
|
||||
self.vmwriter.write_pop('temp', 1)
|
||||
self.vmwriter.write_arithmetic('+')
|
||||
self.vmwriter.write_pop('pointer', 1)
|
||||
self.vmwriter.write_push('temp', 1)
|
||||
self.vmwriter.write_pop('that', 0)
|
||||
self.current_vm.pop()
|
||||
|
||||
def compile_while(self):
|
||||
self.tokenizer.advance() # while ->
|
||||
label1 = self.vmwriter.label_index
|
||||
self.vmwriter.write_lable(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.tokenizer.advance() # ( ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ) ->
|
||||
label2 = self.vmwriter.label_index
|
||||
self.vmwriter.write_if(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.tokenizer.advance() # { ->
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance() # } ->
|
||||
self.vmwriter.write_goto(label1)
|
||||
self.vmwriter.write_lable(label2)
|
||||
|
||||
def compile_return(self):
|
||||
self.tokenizer.advance() # return ->
|
||||
if self.tokenizer.token != ';':
|
||||
self.compile_expression()
|
||||
self.vmwriter.write_return(self.function_type)
|
||||
self.tokenizer.advance() # ; ->
|
||||
|
||||
def compile_if(self):
|
||||
self.tokenizer.advance() # if ->
|
||||
self.tokenizer.advance() # ( ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ) ->
|
||||
label1 = self.vmwriter.label_index
|
||||
self.vmwriter.write_if(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.tokenizer.advance() # { ->
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance() # } ->
|
||||
label2 = self.vmwriter.label_index
|
||||
self.vmwriter.write_goto(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.vmwriter.write_lable(label1)
|
||||
if self.tokenizer.token == 'else':
|
||||
self.tokenizer.advance() # else ->
|
||||
self.tokenizer.advance() # { ->
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance() # } ->
|
||||
self.vmwriter.write_lable(label2)
|
||||
|
||||
def compile_expression(self):
|
||||
self.compile_term()
|
||||
while self.tokenizer.token in ['+', '-', '*', '/', '|', '=', '>', '<', '&']:
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
self.tokenizer.advance() # symbol ->
|
||||
self.compile_term()
|
||||
self.vmwriter.write_arithmetic(self.current_vm[-1])
|
||||
self.current_vm.pop()
|
||||
|
||||
def compile_term(self):
|
||||
if self.tokenizer.token == '(': # expression ()
|
||||
self.tokenizer.advance() # ( ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ) ->
|
||||
elif self.tokenizer.token in ['~', '-']: # uniry op
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
tmp = 'neg' if self.tokenizer.token == '-' else self.tokenizer.token
|
||||
self.tokenizer.advance() # ~ or - ->
|
||||
self.compile_term()
|
||||
self.vmwriter.write_arithmetic(tmp)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type() != 'symbol':
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
self.tokenizer.advance() # integer, string, keyword, varnname, subroutine_name, class_name, var_name ->
|
||||
if self.tokenizer.token == '[': # Array
|
||||
self.tokenizer.advance() # [ ->
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
self.current_vm.pop()
|
||||
self.compile_expression()
|
||||
self.vmwriter.write_arithmetic('+')
|
||||
self.vmwriter.write_pop('pointer', 1)
|
||||
self.vmwriter.write_push('that', 0)
|
||||
self.tokenizer.advance() # ] ->
|
||||
elif self.tokenizer.token == '(': # subroutine_name ()
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
self.vmwriter.write_call(f'{self.class_name}.{self.current_vm[-1]}', count)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token == '.': # method
|
||||
if self.search_type_of_sym(self.current_vm[-1]) is not None:
|
||||
flag = 1
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
else:
|
||||
flag = 0
|
||||
self.tokenizer.advance() # . ->
|
||||
fname = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine name ->
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
if flag == 1:
|
||||
self.vmwriter.write_call(f'{self.search_type_of_sym(self.current_vm[-1])}.{fname}', count + 1)
|
||||
else:
|
||||
self.vmwriter.write_call(f'{self.current_vm[-1]}.{fname}', count)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type(self.current_vm[-1]) == 'stringConstant':
|
||||
self.vmwriter.write_push('constant', len(self.current_vm[-1].strip('"')))
|
||||
self.vmwriter.write_call('String.new', 1)
|
||||
for index, item in enumerate(self.current_vm[-1].strip('"')):
|
||||
self.vmwriter.write_push('constant', ord(item))
|
||||
self.vmwriter.write_call('String.appendChar', 2)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type(self.current_vm[-1]) == 'integerConstant':
|
||||
self.vmwriter.write_push('constant', self.current_vm[-1])
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type(self.current_vm[-1]) == 'identifier':
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'true':
|
||||
self.vmwriter.write_push('constant', '1')
|
||||
self.vmwriter.write_arithmetic('neg')
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'false' or self.current_vm[-1] == 'null':
|
||||
self.vmwriter.write_push('constant', '0')
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'this':
|
||||
self.vmwriter.write_push('pointer', '0')
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'that':
|
||||
self.vmwriter.write_push('pointer', '1')
|
||||
self.current_vm.pop()
|
||||
|
||||
def compile_expression_list(self):
|
||||
count_exp = 0
|
||||
if self.tokenizer.token in ['(', '~', '-'] or self.tokenizer.token_type() != 'symbol':
|
||||
count_exp += 1
|
||||
self.compile_expression()
|
||||
while self.tokenizer.token == ',':
|
||||
count_exp += 1
|
||||
self.tokenizer.advance() # ,
|
||||
self.compile_expression()
|
||||
return count_exp
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
path = os.getcwd()
|
||||
for root, dirs, files in os.walk(path, topdown=False):
|
||||
for name in files:
|
||||
if name[-4:] == 'jack':
|
||||
tokenizer_main = Tokenizer()
|
||||
tokenizer_main.clear_file(Path(root, name))
|
||||
full_path = Path(root, name[:-4] + 'vm')
|
||||
comp_eng_main = CompilationEngine(tokenizer_main, full_path)
|
||||
comp_eng_main.compile_class()
|
||||
Executable
+102
@@ -0,0 +1,102 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Keyboard.jack
|
||||
|
||||
/**
|
||||
* A library for handling user input from the keyboard.
|
||||
*/
|
||||
|
||||
class Keyboard {
|
||||
static Array mem;
|
||||
/** Initializes the keyboard. */
|
||||
function void init() {
|
||||
let mem = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the character of the currently pressed key on the keyboard;
|
||||
* if no key is currently pressed, returns 0.
|
||||
*
|
||||
* Recognizes all ASCII characters, as well as the following keys:
|
||||
* new line = 128 = String.newline()
|
||||
* backspace = 129 = String.backspace()
|
||||
* left arrow = 130
|
||||
* up arrow = 131
|
||||
* right arrow = 132
|
||||
* down arrow = 133
|
||||
* home = 134
|
||||
* End = 135
|
||||
* page up = 136
|
||||
* page down = 137
|
||||
* insert = 138
|
||||
* delete = 139
|
||||
* ESC = 140
|
||||
* F1 - F12 = 141 - 152
|
||||
*/
|
||||
function char keyPressed() {
|
||||
return mem[24576];
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until a key is pressed on the keyboard and released,
|
||||
* then echoes the key to the screen, and returns the character
|
||||
* of the pressed key.
|
||||
*/
|
||||
function char readChar() {
|
||||
var char a, b;
|
||||
do Output.printChar(0);
|
||||
while ((b = 0) | (a > 0)){
|
||||
let a = Keyboard.keyPressed();
|
||||
if (a > 0){
|
||||
let b = a;
|
||||
}
|
||||
}
|
||||
do Output.printChar(String.backSpace());
|
||||
do Output.printChar(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the message on the screen, reads from the keyboard the entered
|
||||
* text until a newline character is detected, echoes the text to the screen,
|
||||
* and returns its value. Also handles user backspaces.
|
||||
*/
|
||||
function String readLine(String message) {
|
||||
var String s, b;
|
||||
var char c;
|
||||
let s = String.new(100);
|
||||
do Output.printString(message);
|
||||
while (true){
|
||||
let c = Keyboard.readChar();
|
||||
if (c = 128){
|
||||
return s;
|
||||
}
|
||||
else{
|
||||
if (c = 129){
|
||||
do s.eraseLastChar();
|
||||
}
|
||||
else{
|
||||
do s.appendChar(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the message on the screen, reads from the keyboard the entered
|
||||
* text until a newline character is detected, echoes the text to the screen,
|
||||
* and returns its integer value (until the first non-digit character in the
|
||||
* entered text is detected). Also handles user backspaces.
|
||||
*/
|
||||
function int readInt(String message) {
|
||||
var starting a;
|
||||
var int b;
|
||||
let a = Keyboard.readLine(message);
|
||||
let b = String.intValue(a);
|
||||
do String.dispose(a);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
Executable
+103
@@ -0,0 +1,103 @@
|
||||
function Keyboard.init 0
|
||||
push constant 0
|
||||
pop static 0
|
||||
push constant 0
|
||||
return
|
||||
function Keyboard.keyPressed 0
|
||||
push static 0
|
||||
push constant 24576
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
return
|
||||
function Keyboard.readChar 2
|
||||
push constant 0
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
label L0
|
||||
push local 1
|
||||
push constant 0
|
||||
eq
|
||||
push local 0
|
||||
push constant 0
|
||||
gt
|
||||
or
|
||||
not
|
||||
if-goto L1
|
||||
call Keyboard.keyPressed 0
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L2
|
||||
push local 0
|
||||
pop local 1
|
||||
goto L3
|
||||
label L2
|
||||
label L3
|
||||
goto L0
|
||||
label L1
|
||||
call String.backSpace 0
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
call Output.printChar 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
return
|
||||
function Keyboard.readLine 3
|
||||
push constant 100
|
||||
call String.new 1
|
||||
pop local 0
|
||||
push argument 0
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
label L4
|
||||
push constant 1
|
||||
neg
|
||||
not
|
||||
if-goto L5
|
||||
call Keyboard.readChar 0
|
||||
pop local 2
|
||||
push local 2
|
||||
push constant 128
|
||||
eq
|
||||
not
|
||||
if-goto L6
|
||||
push local 0
|
||||
return
|
||||
goto L7
|
||||
label L6
|
||||
push local 2
|
||||
push constant 129
|
||||
eq
|
||||
not
|
||||
if-goto L8
|
||||
push local 0
|
||||
call String.eraseLastChar 1
|
||||
pop temp 0
|
||||
goto L9
|
||||
label L8
|
||||
push local 0
|
||||
push local 2
|
||||
call String.appendChar 2
|
||||
pop temp 0
|
||||
label L9
|
||||
label L7
|
||||
goto L4
|
||||
label L5
|
||||
push local 0
|
||||
return
|
||||
function Keyboard.readInt 2
|
||||
push argument 0
|
||||
call Keyboard.readLine 1
|
||||
pop local 0
|
||||
push local 0
|
||||
call String.intValue 1
|
||||
pop local 1
|
||||
push local 0
|
||||
call String.dispose 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
return
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/StringTest/Main.jack
|
||||
|
||||
/** Test program for the OS String class. */
|
||||
class Main {
|
||||
|
||||
/** Performs various string manipulations and displays their results. */
|
||||
function void main() {
|
||||
var String s;
|
||||
var String i;
|
||||
|
||||
let s = String.new(0); // a zero-capacity string should be supported
|
||||
do s.dispose();
|
||||
|
||||
let s = String.new(6); // capacity 6, make sure that length 5 is displayed
|
||||
let s = s.appendChar(97);
|
||||
let s = s.appendChar(98);
|
||||
let s = s.appendChar(99);
|
||||
let s = s.appendChar(100);
|
||||
let s = s.appendChar(101);
|
||||
do Output.printString("new: ");
|
||||
do Output.printString(s); // new, appendChar: abcde
|
||||
do Output.println();
|
||||
|
||||
let i = String.new(6);
|
||||
do i.setInt(12345);
|
||||
do Output.printString("setInt: ");
|
||||
do Output.printString(i); // setInt: 12345
|
||||
do Output.println();
|
||||
|
||||
do i.setInt(-32767);
|
||||
do Output.printString("setInt: ");
|
||||
do Output.printString(i); // setInt: -32767
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("length: ");
|
||||
do Output.printInt(s.length()); // length: 5
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("charAt[2]: ");
|
||||
do Output.printInt(s.charAt(2)); // charAt[2]: 99
|
||||
do Output.println();
|
||||
|
||||
do s.setCharAt(2, 45);
|
||||
do Output.printString("setCharAt(2,'-'): ");
|
||||
do Output.printString(s); // setCharAt(2,'-'): ab-de
|
||||
do Output.println();
|
||||
|
||||
do s.eraseLastChar();
|
||||
do Output.printString("eraseLastChar: ");
|
||||
do Output.printString(s); // eraseLastChar: ab-d
|
||||
do Output.println();
|
||||
|
||||
let s = "456";
|
||||
do Output.printString("intValue: ");
|
||||
do Output.printInt(s.intValue()); // intValue: 456
|
||||
do Output.println();
|
||||
|
||||
let s = "-32123";
|
||||
do Output.printString("intValue: ");
|
||||
do Output.printInt(s.intValue()); // intValue: -32123
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("backSpace: ");
|
||||
do Output.printInt(String.backSpace()); // backSpace: 129
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("doubleQuote: ");
|
||||
do Output.printInt(String.doubleQuote());// doubleQuote: 34
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("newLine: ");
|
||||
do Output.printInt(String.newLine()); // newLine: 128
|
||||
do Output.println();
|
||||
|
||||
do i.dispose();
|
||||
do s.dispose();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+447
@@ -0,0 +1,447 @@
|
||||
function Main.main 2
|
||||
push constant 0
|
||||
call String.new 1
|
||||
pop local 0
|
||||
push local 0
|
||||
call String.dispose 1
|
||||
pop temp 0
|
||||
push constant 6
|
||||
call String.new 1
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 98
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push constant 5
|
||||
call String.new 1
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 119
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 6
|
||||
call String.new 1
|
||||
pop local 1
|
||||
push local 1
|
||||
push constant 12345
|
||||
call String.setInt 2
|
||||
pop temp 0
|
||||
push constant 8
|
||||
call String.new 1
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 73
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push local 1
|
||||
push constant 32767
|
||||
neg
|
||||
call String.setInt 2
|
||||
pop temp 0
|
||||
push constant 8
|
||||
call String.new 1
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 73
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 8
|
||||
call String.new 1
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 103
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call String.length 1
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 11
|
||||
call String.new 1
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 65
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 91
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 93
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 2
|
||||
call String.charAt 2
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 2
|
||||
push constant 45
|
||||
call String.setCharAt 3
|
||||
pop temp 0
|
||||
push constant 18
|
||||
call String.new 1
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 67
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 65
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 40
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 44
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 45
|
||||
call String.appendChar 2
|
||||
push constant 39
|
||||
call String.appendChar 2
|
||||
push constant 41
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push local 0
|
||||
call String.eraseLastChar 1
|
||||
pop temp 0
|
||||
push constant 15
|
||||
call String.new 1
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 76
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 67
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 3
|
||||
call String.new 1
|
||||
push constant 52
|
||||
call String.appendChar 2
|
||||
push constant 53
|
||||
call String.appendChar 2
|
||||
push constant 54
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push constant 10
|
||||
call String.new 1
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 86
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call String.intValue 1
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 6
|
||||
call String.new 1
|
||||
push constant 45
|
||||
call String.appendChar 2
|
||||
push constant 51
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 49
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 51
|
||||
call String.appendChar 2
|
||||
pop local 0
|
||||
push constant 10
|
||||
call String.new 1
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 86
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call String.intValue 1
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 11
|
||||
call String.new 1
|
||||
push constant 98
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 107
|
||||
call String.appendChar 2
|
||||
push constant 83
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call String.backSpace 0
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 13
|
||||
call String.new 1
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 98
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 81
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call String.doubleQuote 0
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 9
|
||||
call String.new 1
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 119
|
||||
call String.appendChar 2
|
||||
push constant 76
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
call String.newLine 0
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push local 1
|
||||
call String.dispose 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call String.dispose 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+143
@@ -0,0 +1,143 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Math.jack
|
||||
|
||||
/**
|
||||
* A library of commonly used mathematical functions.
|
||||
* Note: Jack compilers implement multiplication and division using OS method calls.
|
||||
*/
|
||||
class Math {
|
||||
static Array st;
|
||||
static int division_tmp, f;
|
||||
|
||||
/** Initializes the library. */
|
||||
function void init() {
|
||||
var int a;
|
||||
let st = Array.new(16);
|
||||
let st[0] = 1;
|
||||
while (a < 15){
|
||||
let a = a + 1;
|
||||
let st[a] = st[a - 1] + st[a - 1];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the absolute value of x. */
|
||||
function int abs(int x) {
|
||||
if (x > 0){
|
||||
return x;
|
||||
}
|
||||
return -x;
|
||||
}
|
||||
|
||||
/** Returns the product of x and y.
|
||||
* When a Jack compiler detects the multiplication operator '*' in the
|
||||
* program's code, it handles it by invoking this method. In other words,
|
||||
* the Jack expressions x*y and multiply(x,y) return the same value.
|
||||
*/
|
||||
function int multiply(int x, int y) {
|
||||
var int sum, temp, y_comp, i, neg;
|
||||
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
|
||||
let x = Math.abs(x);
|
||||
let y = Math.abs(y);
|
||||
if (x < y){
|
||||
let temp = x;
|
||||
let x = y;
|
||||
let y = temp;
|
||||
}
|
||||
if (y = 1){
|
||||
if(neg){
|
||||
return -x;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
while((y_comp - 1) < (y - 1)){
|
||||
if ((st[i] & y) > 0) {
|
||||
let sum = sum + x;
|
||||
let y_comp = y_comp + st[i];
|
||||
}
|
||||
let x = x + x;
|
||||
let i = i + 1;
|
||||
}
|
||||
if(neg){
|
||||
let sum = -sum;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/** Returns the integer part of x/y.
|
||||
* When a Jack compiler detects the multiplication operator '/' in the
|
||||
* program's code, it handles it by invoking this method. In other words,
|
||||
* the Jack expressions x/y and divide(x,y) return the same value.
|
||||
*/
|
||||
function int divide(int x, int y) {
|
||||
var int q, neg;
|
||||
if (f = 0){
|
||||
let division_tmp = 0;
|
||||
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
|
||||
let x = Math.abs(x);
|
||||
let y = Math.abs(y);
|
||||
if (y = 0){
|
||||
do Sys.error(3);
|
||||
}
|
||||
let f = 1;
|
||||
}
|
||||
if ((y > x) | (y < 0)){
|
||||
return 0;
|
||||
}
|
||||
let q = Math.divide(x, y + y);
|
||||
let f = 0;
|
||||
let q = Math.abs(q);
|
||||
if ((q & 1) = 1){
|
||||
let division_tmp = division_tmp + y + y;
|
||||
}
|
||||
if (x - division_tmp < y){
|
||||
if (neg){
|
||||
return -(q + q);
|
||||
}
|
||||
return q + q;
|
||||
}
|
||||
else{
|
||||
if (neg){
|
||||
return -(q + q + 1);
|
||||
}
|
||||
return q + q + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the integer part of the square root of x. */
|
||||
function int sqrt(int x) {
|
||||
var int j, b, d, y;
|
||||
|
||||
if (x < 0){
|
||||
do Sys.error(4);
|
||||
}
|
||||
let j = 7;
|
||||
while (j > -1){
|
||||
let d = y + st[j];
|
||||
let b = d * d;
|
||||
if ((~(b > x)) & (b > 0)){
|
||||
let y = d;
|
||||
}
|
||||
let j = j - 1;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/** Returns the greater number. */
|
||||
function int max(int a, int b) {
|
||||
if (a > b){
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/** Returns the smaller number. */
|
||||
function int min(int a, int b) {
|
||||
if (a < b){
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
Executable
+388
@@ -0,0 +1,388 @@
|
||||
function Math.init 1
|
||||
push constant 16
|
||||
call Array.new 1
|
||||
pop static 0
|
||||
push static 0
|
||||
push constant 0
|
||||
push constant 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
label L0
|
||||
push local 0
|
||||
push constant 15
|
||||
lt
|
||||
not
|
||||
if-goto L1
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop local 0
|
||||
push static 0
|
||||
push local 0
|
||||
push static 0
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push static 0
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
goto L0
|
||||
label L1
|
||||
push constant 0
|
||||
return
|
||||
function Math.abs 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L2
|
||||
push argument 0
|
||||
return
|
||||
goto L3
|
||||
label L2
|
||||
label L3
|
||||
push argument 0
|
||||
neg
|
||||
return
|
||||
function Math.multiply 5
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 1
|
||||
push constant 0
|
||||
gt
|
||||
and
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
and
|
||||
or
|
||||
pop local 4
|
||||
push argument 0
|
||||
call Math.abs 1
|
||||
pop argument 0
|
||||
push argument 1
|
||||
call Math.abs 1
|
||||
pop argument 1
|
||||
push argument 0
|
||||
push argument 1
|
||||
lt
|
||||
not
|
||||
if-goto L4
|
||||
push argument 0
|
||||
pop local 1
|
||||
push argument 1
|
||||
pop argument 0
|
||||
push local 1
|
||||
pop argument 1
|
||||
goto L5
|
||||
label L4
|
||||
label L5
|
||||
push argument 1
|
||||
push constant 1
|
||||
eq
|
||||
not
|
||||
if-goto L6
|
||||
push local 4
|
||||
not
|
||||
if-goto L7
|
||||
push argument 0
|
||||
neg
|
||||
return
|
||||
goto L8
|
||||
label L7
|
||||
label L8
|
||||
push argument 0
|
||||
return
|
||||
goto L9
|
||||
label L6
|
||||
label L9
|
||||
label L10
|
||||
push local 2
|
||||
push constant 1
|
||||
sub
|
||||
push argument 1
|
||||
push constant 1
|
||||
sub
|
||||
lt
|
||||
not
|
||||
if-goto L11
|
||||
push static 0
|
||||
push local 3
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 1
|
||||
and
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L12
|
||||
push local 0
|
||||
push argument 0
|
||||
add
|
||||
pop local 0
|
||||
push local 2
|
||||
push static 0
|
||||
push local 3
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop local 2
|
||||
goto L13
|
||||
label L12
|
||||
label L13
|
||||
push argument 0
|
||||
push argument 0
|
||||
add
|
||||
pop argument 0
|
||||
push local 3
|
||||
push constant 1
|
||||
add
|
||||
pop local 3
|
||||
goto L10
|
||||
label L11
|
||||
push local 4
|
||||
not
|
||||
if-goto L14
|
||||
push local 0
|
||||
neg
|
||||
pop local 0
|
||||
goto L15
|
||||
label L14
|
||||
label L15
|
||||
push local 0
|
||||
return
|
||||
function Math.divide 2
|
||||
push static 2
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L16
|
||||
push constant 0
|
||||
pop static 1
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
push argument 1
|
||||
push constant 0
|
||||
gt
|
||||
and
|
||||
push argument 0
|
||||
push constant 0
|
||||
gt
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
and
|
||||
or
|
||||
pop local 1
|
||||
push argument 0
|
||||
call Math.abs 1
|
||||
pop argument 0
|
||||
push argument 1
|
||||
call Math.abs 1
|
||||
pop argument 1
|
||||
push argument 1
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L17
|
||||
push constant 3
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L18
|
||||
label L17
|
||||
label L18
|
||||
push constant 1
|
||||
pop static 2
|
||||
goto L19
|
||||
label L16
|
||||
label L19
|
||||
push argument 1
|
||||
push argument 0
|
||||
gt
|
||||
push argument 1
|
||||
push constant 0
|
||||
lt
|
||||
or
|
||||
not
|
||||
if-goto L20
|
||||
push constant 0
|
||||
return
|
||||
goto L21
|
||||
label L20
|
||||
label L21
|
||||
push argument 0
|
||||
push argument 1
|
||||
push argument 1
|
||||
add
|
||||
call Math.divide 2
|
||||
pop local 0
|
||||
push constant 0
|
||||
pop static 2
|
||||
push local 0
|
||||
call Math.abs 1
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 1
|
||||
and
|
||||
push constant 1
|
||||
eq
|
||||
not
|
||||
if-goto L22
|
||||
push static 1
|
||||
push argument 1
|
||||
add
|
||||
push argument 1
|
||||
add
|
||||
pop static 1
|
||||
goto L23
|
||||
label L22
|
||||
label L23
|
||||
push argument 0
|
||||
push static 1
|
||||
sub
|
||||
push argument 1
|
||||
lt
|
||||
not
|
||||
if-goto L24
|
||||
push local 1
|
||||
not
|
||||
if-goto L25
|
||||
push local 0
|
||||
push local 0
|
||||
add
|
||||
neg
|
||||
return
|
||||
goto L26
|
||||
label L25
|
||||
label L26
|
||||
push local 0
|
||||
push local 0
|
||||
add
|
||||
return
|
||||
goto L27
|
||||
label L24
|
||||
push local 1
|
||||
not
|
||||
if-goto L28
|
||||
push local 0
|
||||
push local 0
|
||||
add
|
||||
push constant 1
|
||||
add
|
||||
neg
|
||||
return
|
||||
goto L29
|
||||
label L28
|
||||
label L29
|
||||
push local 0
|
||||
push local 0
|
||||
add
|
||||
push constant 1
|
||||
add
|
||||
return
|
||||
label L27
|
||||
function Math.sqrt 4
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L30
|
||||
push constant 4
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L31
|
||||
label L30
|
||||
label L31
|
||||
push constant 7
|
||||
pop local 0
|
||||
label L32
|
||||
push local 0
|
||||
push constant 1
|
||||
neg
|
||||
gt
|
||||
not
|
||||
if-goto L33
|
||||
push local 3
|
||||
push static 0
|
||||
push local 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop local 2
|
||||
push local 2
|
||||
push local 2
|
||||
call Math.multiply 2
|
||||
pop local 1
|
||||
push local 1
|
||||
push argument 0
|
||||
gt
|
||||
not
|
||||
push local 1
|
||||
push constant 0
|
||||
gt
|
||||
and
|
||||
not
|
||||
if-goto L34
|
||||
push local 2
|
||||
pop local 3
|
||||
goto L35
|
||||
label L34
|
||||
label L35
|
||||
push local 0
|
||||
push constant 1
|
||||
sub
|
||||
pop local 0
|
||||
goto L32
|
||||
label L33
|
||||
push local 3
|
||||
return
|
||||
function Math.max 0
|
||||
push argument 0
|
||||
push argument 1
|
||||
gt
|
||||
not
|
||||
if-goto L36
|
||||
push argument 0
|
||||
return
|
||||
goto L37
|
||||
label L36
|
||||
label L37
|
||||
push argument 1
|
||||
return
|
||||
function Math.min 0
|
||||
push argument 0
|
||||
push argument 1
|
||||
lt
|
||||
not
|
||||
if-goto L38
|
||||
push argument 0
|
||||
return
|
||||
goto L39
|
||||
label L38
|
||||
label L39
|
||||
push argument 1
|
||||
return
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Memory.jack
|
||||
|
||||
/**
|
||||
* This library provides two services: direct access to the computer's main
|
||||
* memory (RAM), and allocation and recycling of memory blocks. The Hack RAM
|
||||
* consists of 32,768 words, each holding a 16-bit binary number.
|
||||
*/
|
||||
class Memory {
|
||||
static Array mem;
|
||||
/** Initializes the class. */
|
||||
function void init() {
|
||||
let mem = 0;
|
||||
let mem[2048] = 14334;
|
||||
let mem[2049] = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the RAM value at the given address. */
|
||||
function int peek(int address) {
|
||||
return mem[address];
|
||||
}
|
||||
|
||||
/** Sets the RAM value at the given address to the given value. */
|
||||
function void poke(int address, int value) {
|
||||
let mem[address] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Finds an available RAM block of the given size and returns
|
||||
* a reference to its base address. */
|
||||
function int alloc(int size) {
|
||||
var Array current_block;
|
||||
var int tmp;
|
||||
let current_block = 2048;
|
||||
if (size < 0){
|
||||
do Sys.error(5);
|
||||
}
|
||||
if (size = 0){
|
||||
let size = 1;
|
||||
}
|
||||
while (current_block[0] < (size + 2)) {
|
||||
let current_block = current_block[1];
|
||||
}
|
||||
let current_block[0] = current_block[0] - size - 2;
|
||||
let current_block = current_block + current_block[0] + 2;
|
||||
let current_block[0] = size;
|
||||
return current_block + 2;
|
||||
}
|
||||
|
||||
/** De-allocates the given object (cast as an array) by making
|
||||
* it available for future allocations. */
|
||||
function void deAlloc(Array o) {
|
||||
var Array current_block;
|
||||
let current_block = 2048;
|
||||
let o[1]= current_block[1];
|
||||
let current_block[1] = o;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
Executable
+147
@@ -0,0 +1,147 @@
|
||||
function Memory.init 0
|
||||
push constant 0
|
||||
pop static 0
|
||||
push static 0
|
||||
push constant 2048
|
||||
push constant 14334
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push static 0
|
||||
push constant 2049
|
||||
push constant 1
|
||||
neg
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
function Memory.peek 0
|
||||
push static 0
|
||||
push argument 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
return
|
||||
function Memory.poke 0
|
||||
push static 0
|
||||
push argument 0
|
||||
push argument 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
function Memory.alloc 2
|
||||
push constant 2048
|
||||
pop local 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L0
|
||||
push constant 5
|
||||
call Sys.error 1
|
||||
pop temp 0
|
||||
goto L1
|
||||
label L0
|
||||
label L1
|
||||
push argument 0
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L2
|
||||
push constant 1
|
||||
pop argument 0
|
||||
goto L3
|
||||
label L2
|
||||
label L3
|
||||
label L4
|
||||
push local 0
|
||||
push constant 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 0
|
||||
push constant 2
|
||||
add
|
||||
lt
|
||||
not
|
||||
if-goto L5
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop local 0
|
||||
goto L4
|
||||
label L5
|
||||
push local 0
|
||||
push constant 0
|
||||
push local 0
|
||||
push constant 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push argument 0
|
||||
sub
|
||||
push constant 2
|
||||
sub
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push local 0
|
||||
push constant 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
push constant 2
|
||||
add
|
||||
pop local 0
|
||||
push local 0
|
||||
push constant 0
|
||||
push argument 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 2
|
||||
add
|
||||
return
|
||||
function Memory.deAlloc 1
|
||||
push constant 2048
|
||||
pop local 0
|
||||
push argument 0
|
||||
push constant 1
|
||||
push local 0
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 1
|
||||
push argument 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+299
@@ -0,0 +1,299 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Output.jack
|
||||
|
||||
/**
|
||||
* A library of functions for writing text on the screen.
|
||||
* The Hack physical screen consists of 512 rows of 256 pixels each.
|
||||
* The library uses a fixed font, in which each character is displayed
|
||||
* within a frame which is 11 pixels high (including 1 pixel for inter-line
|
||||
* spacing) and 8 pixels wide (including 2 pixels for inter-character spacing).
|
||||
* The resulting grid accommodates 23 rows (indexed 0..22, top to bottom)
|
||||
* of 64 characters each (indexed 0..63, left to right). The top left
|
||||
* character position on the screen is indexed (0,0). A cursor, implemented
|
||||
* as a small filled square, indicates where the next character will be displayed.
|
||||
*/
|
||||
class Output {
|
||||
|
||||
// Character map for displaying characters
|
||||
static Array charMaps;
|
||||
static int address;
|
||||
static bool half;
|
||||
|
||||
/** Initializes the screen, and locates the cursor at the screen's top-left. */
|
||||
function void init() {
|
||||
do Output.initMap();
|
||||
do Output.moveCursor(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Initializes the character map array
|
||||
function void initMap() {
|
||||
var int i;
|
||||
|
||||
let charMaps = Array.new(127);
|
||||
|
||||
// Black square, used for displaying non-printable characters.
|
||||
do Output.create(0,63,63,63,63,63,63,63,63,63,0,0);
|
||||
|
||||
// Assigns the bitmap for each character in the charachter set.
|
||||
// The first parameter is the character index, the next 11 numbers
|
||||
// are the values of each row in the frame that represents this character.
|
||||
do Output.create(32,0,0,0,0,0,0,0,0,0,0,0); //
|
||||
do Output.create(33,12,30,30,30,12,12,0,12,12,0,0); // !
|
||||
do Output.create(34,54,54,20,0,0,0,0,0,0,0,0); // "
|
||||
do Output.create(35,0,18,18,63,18,18,63,18,18,0,0); // #
|
||||
do Output.create(36,12,30,51,3,30,48,51,30,12,12,0); // $
|
||||
do Output.create(37,0,0,35,51,24,12,6,51,49,0,0); // %
|
||||
do Output.create(38,12,30,30,12,54,27,27,27,54,0,0); // &
|
||||
do Output.create(39,12,12,6,0,0,0,0,0,0,0,0); // '
|
||||
do Output.create(40,24,12,6,6,6,6,6,12,24,0,0); // (
|
||||
do Output.create(41,6,12,24,24,24,24,24,12,6,0,0); // )
|
||||
do Output.create(42,0,0,0,51,30,63,30,51,0,0,0); // *
|
||||
do Output.create(43,0,0,0,12,12,63,12,12,0,0,0); // +
|
||||
do Output.create(44,0,0,0,0,0,0,0,12,12,6,0); // ,
|
||||
do Output.create(45,0,0,0,0,0,63,0,0,0,0,0); // -
|
||||
do Output.create(46,0,0,0,0,0,0,0,12,12,0,0); // .
|
||||
do Output.create(47,0,0,32,48,24,12,6,3,1,0,0); // /
|
||||
|
||||
do Output.create(48,12,30,51,51,51,51,51,30,12,0,0); // 0
|
||||
do Output.create(49,12,14,15,12,12,12,12,12,63,0,0); // 1
|
||||
do Output.create(50,30,51,48,24,12,6,3,51,63,0,0); // 2
|
||||
do Output.create(51,30,51,48,48,28,48,48,51,30,0,0); // 3
|
||||
do Output.create(52,16,24,28,26,25,63,24,24,60,0,0); // 4
|
||||
do Output.create(53,63,3,3,31,48,48,48,51,30,0,0); // 5
|
||||
do Output.create(54,28,6,3,3,31,51,51,51,30,0,0); // 6
|
||||
do Output.create(55,63,49,48,48,24,12,12,12,12,0,0); // 7
|
||||
do Output.create(56,30,51,51,51,30,51,51,51,30,0,0); // 8
|
||||
do Output.create(57,30,51,51,51,62,48,48,24,14,0,0); // 9
|
||||
|
||||
do Output.create(58,0,0,12,12,0,0,12,12,0,0,0); // :
|
||||
do Output.create(59,0,0,12,12,0,0,12,12,6,0,0); // ;
|
||||
do Output.create(60,0,0,24,12,6,3,6,12,24,0,0); // <
|
||||
do Output.create(61,0,0,0,63,0,0,63,0,0,0,0); // =
|
||||
do Output.create(62,0,0,3,6,12,24,12,6,3,0,0); // >
|
||||
do Output.create(64,30,51,51,59,59,59,27,3,30,0,0); // @
|
||||
do Output.create(63,30,51,51,24,12,12,0,12,12,0,0); // ?
|
||||
|
||||
do Output.create(65,12,30,51,51,63,51,51,51,51,0,0); // A ** TO BE FILLED **
|
||||
do Output.create(66,31,51,51,51,31,51,51,51,31,0,0); // B
|
||||
do Output.create(67,28,54,35,3,3,3,35,54,28,0,0); // C
|
||||
do Output.create(68,15,27,51,51,51,51,51,27,15,0,0); // D
|
||||
do Output.create(69,63,51,35,11,15,11,35,51,63,0,0); // E
|
||||
do Output.create(70,63,51,35,11,15,11,3,3,3,0,0); // F
|
||||
do Output.create(71,28,54,35,3,59,51,51,54,44,0,0); // G
|
||||
do Output.create(72,51,51,51,51,63,51,51,51,51,0,0); // H
|
||||
do Output.create(73,30,12,12,12,12,12,12,12,30,0,0); // I
|
||||
do Output.create(74,60,24,24,24,24,24,27,27,14,0,0); // J
|
||||
do Output.create(75,51,51,51,27,15,27,51,51,51,0,0); // K
|
||||
do Output.create(76,3,3,3,3,3,3,35,51,63,0,0); // L
|
||||
do Output.create(77,33,51,63,63,51,51,51,51,51,0,0); // M
|
||||
do Output.create(78,51,51,55,55,63,59,59,51,51,0,0); // N
|
||||
do Output.create(79,30,51,51,51,51,51,51,51,30,0,0); // O
|
||||
do Output.create(80,31,51,51,51,31,3,3,3,3,0,0); // P
|
||||
do Output.create(81,30,51,51,51,51,51,63,59,30,48,0);// Q
|
||||
do Output.create(82,31,51,51,51,31,27,51,51,51,0,0); // R
|
||||
do Output.create(83,30,51,51,6,28,48,51,51,30,0,0); // S
|
||||
do Output.create(84,63,63,45,12,12,12,12,12,30,0,0); // T
|
||||
do Output.create(85,51,51,51,51,51,51,51,51,30,0,0); // U
|
||||
do Output.create(86,51,51,51,51,51,30,30,12,12,0,0); // V
|
||||
do Output.create(87,51,51,51,51,51,63,63,63,18,0,0); // W
|
||||
do Output.create(88,51,51,30,30,12,30,30,51,51,0,0); // X
|
||||
do Output.create(89,51,51,51,51,30,12,12,12,30,0,0); // Y
|
||||
do Output.create(90,63,51,49,24,12,6,35,51,63,0,0); // Z
|
||||
|
||||
do Output.create(91,30,6,6,6,6,6,6,6,30,0,0); // [
|
||||
do Output.create(92,0,0,1,3,6,12,24,48,32,0,0); // \
|
||||
do Output.create(93,30,24,24,24,24,24,24,24,30,0,0); // ]
|
||||
do Output.create(94,8,28,54,0,0,0,0,0,0,0,0); // ^
|
||||
do Output.create(95,0,0,0,0,0,0,0,0,0,63,0); // _
|
||||
do Output.create(96,6,12,24,0,0,0,0,0,0,0,0); // `
|
||||
|
||||
do Output.create(97,0,0,0,14,24,30,27,27,54,0,0); // a
|
||||
do Output.create(98,3,3,3,15,27,51,51,51,30,0,0); // b
|
||||
do Output.create(99,0,0,0,30,51,3,3,51,30,0,0); // c
|
||||
do Output.create(100,48,48,48,60,54,51,51,51,30,0,0); // d
|
||||
do Output.create(101,0,0,0,30,51,63,3,51,30,0,0); // e
|
||||
do Output.create(102,28,54,38,6,15,6,6,6,15,0,0); // f
|
||||
do Output.create(103,0,0,30,51,51,51,62,48,51,30,0); // g
|
||||
do Output.create(104,3,3,3,27,55,51,51,51,51,0,0); // h
|
||||
do Output.create(105,12,12,0,14,12,12,12,12,30,0,0); // i
|
||||
do Output.create(106,48,48,0,56,48,48,48,48,51,30,0); // j
|
||||
do Output.create(107,3,3,3,51,27,15,15,27,51,0,0); // k
|
||||
do Output.create(108,14,12,12,12,12,12,12,12,30,0,0); // l
|
||||
do Output.create(109,0,0,0,29,63,43,43,43,43,0,0); // m
|
||||
do Output.create(110,0,0,0,29,51,51,51,51,51,0,0); // n
|
||||
do Output.create(111,0,0,0,30,51,51,51,51,30,0,0); // o
|
||||
do Output.create(112,0,0,0,30,51,51,51,31,3,3,0); // p
|
||||
do Output.create(113,0,0,0,30,51,51,51,62,48,48,0); // q
|
||||
do Output.create(114,0,0,0,29,55,51,3,3,7,0,0); // r
|
||||
do Output.create(115,0,0,0,30,51,6,24,51,30,0,0); // s
|
||||
do Output.create(116,4,6,6,15,6,6,6,54,28,0,0); // t
|
||||
do Output.create(117,0,0,0,27,27,27,27,27,54,0,0); // u
|
||||
do Output.create(118,0,0,0,51,51,51,51,30,12,0,0); // v
|
||||
do Output.create(119,0,0,0,51,51,51,63,63,18,0,0); // w
|
||||
do Output.create(120,0,0,0,51,30,12,12,30,51,0,0); // x
|
||||
do Output.create(121,0,0,0,51,51,51,62,48,24,15,0); // y
|
||||
do Output.create(122,0,0,0,63,27,12,6,51,63,0,0); // z
|
||||
|
||||
do Output.create(123,56,12,12,12,7,12,12,12,56,0,0); // {
|
||||
do Output.create(124,12,12,12,12,12,12,12,12,12,0,0); // |
|
||||
do Output.create(125,7,12,12,12,56,12,12,12,7,0,0); // }
|
||||
do Output.create(126,38,45,25,0,0,0,0,0,0,0,0); // ~
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Creates the character map array of the given character index, using the given values.
|
||||
function void create(int index, int a, int b, int c, int d, int e,
|
||||
int f, int g, int h, int i, int j, int k) {
|
||||
var Array map;
|
||||
|
||||
let map = Array.new(11);
|
||||
let charMaps[index] = map;
|
||||
|
||||
let map[0] = a;
|
||||
let map[1] = b;
|
||||
let map[2] = c;
|
||||
let map[3] = d;
|
||||
let map[4] = e;
|
||||
let map[5] = f;
|
||||
let map[6] = g;
|
||||
let map[7] = h;
|
||||
let map[8] = i;
|
||||
let map[9] = j;
|
||||
let map[10] = k;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Returns the character map (array of size 11) of the given character.
|
||||
// If the given character is invalid or non-printable, returns the
|
||||
// character map of a black square.
|
||||
function Array getMap(char c) {
|
||||
if ((c < 32) | (c > 126)) {
|
||||
let c = 0;
|
||||
}
|
||||
return charMaps[c];
|
||||
}
|
||||
|
||||
/** Moves the cursor to the j-th column of the i-th row,
|
||||
* and erases the character displayed there. */
|
||||
function void moveCursor(int i, int j) {
|
||||
var int co,display;
|
||||
var Array r,ch;
|
||||
if (j = 0){
|
||||
let half = true;
|
||||
}
|
||||
else{
|
||||
let half = (j / 2) * 2 = j; // chetno true, 1vaa chast
|
||||
}
|
||||
let address = (352 * i) + (j / 2) + 16384;
|
||||
let ch = Output.getMap(32);
|
||||
|
||||
while (co < 11){
|
||||
if (half){
|
||||
let display = r[address] & (-256);
|
||||
let r[address] = ch[co] | display;
|
||||
}
|
||||
else{
|
||||
let display = r[address] & 255;
|
||||
let r[address] = (ch[co]*256) | display;
|
||||
}
|
||||
let co = co + 1;
|
||||
let address = address + 32;
|
||||
}
|
||||
let address = address - 352;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given character at the cursor location,
|
||||
* and advances the cursor one column forward. */
|
||||
function void printChar(char c) {
|
||||
var Array ch;
|
||||
var Array r;
|
||||
var int co;
|
||||
var int ds;
|
||||
let ch = Output.getMap(c);
|
||||
while (co < 11){
|
||||
if (half){
|
||||
let ds = r[address] & (-256);
|
||||
let r[address] = ch[co] | ds;
|
||||
}
|
||||
else{
|
||||
let ds = r[address] & 255;
|
||||
let r[address] = (ch[co]*256) | ds;
|
||||
}
|
||||
let co = co + 1;
|
||||
let address = address + 32;
|
||||
}
|
||||
|
||||
if (half){
|
||||
let address = address - 352;
|
||||
let half = false;
|
||||
}
|
||||
else{
|
||||
if (address > 24480){
|
||||
let address = 16384;
|
||||
let half = true;
|
||||
}
|
||||
else{
|
||||
let address = address - 351;
|
||||
let half = true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** displays the given string starting at the cursor location,
|
||||
* and advances the cursor appropriately. */
|
||||
function void printString(String s) {
|
||||
var int i, length;
|
||||
let length = s.length();
|
||||
while (i < length){
|
||||
do Output.printChar(s.charAt(i));
|
||||
let i = i + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given integer starting at the cursor location,
|
||||
* and advances the cursor appropriately. */
|
||||
function void printInt(int i) {
|
||||
var String s;
|
||||
let s = String.new(6);
|
||||
do s.setInt(i);
|
||||
do Output.printString(s);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Advances the cursor to the beginning of the next line. */
|
||||
function void println() {
|
||||
var int row;
|
||||
let row = (((address - 16384) / 32)/11) + 1;
|
||||
if (row > 32){
|
||||
let row = 0;
|
||||
}
|
||||
do Output.moveCursor(row, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the cursor one column back. */
|
||||
function void backSpace() {
|
||||
if (address = 16384){
|
||||
let address = 24191;
|
||||
let half = true;
|
||||
return;
|
||||
}
|
||||
if (half){
|
||||
|
||||
let address = address - 1;
|
||||
let half = false;
|
||||
}
|
||||
else{
|
||||
let half = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+1793
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user