Add solutions for part 1
This commit is contained in:
23
projects/12/Array.jack
Normal file
23
projects/12/Array.jack
Normal file
@@ -0,0 +1,23 @@
|
||||
// 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) {
|
||||
}
|
||||
|
||||
/** Disposes this array. */
|
||||
method void dispose() {
|
||||
}
|
||||
}
|
||||
29
projects/12/ArrayTest/Array.jack
Normal file
29
projects/12/ArrayTest/Array.jack
Normal file
@@ -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) {
|
||||
return Memory.alloc(size);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Disposes this array. */
|
||||
method void dispose() {
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
2
projects/12/ArrayTest/ArrayTest.cmp
Normal file
2
projects/12/ArrayTest/ArrayTest.cmp
Normal file
@@ -0,0 +1,2 @@
|
||||
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|
|
||||
| 222 | 122 | 100 | 10 |
|
||||
15
projects/12/ArrayTest/ArrayTest.tst
Normal file
15
projects/12/ArrayTest/ArrayTest.tst
Normal file
@@ -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;
|
||||
40
projects/12/ArrayTest/Main.jack
Normal file
40
projects/12/ArrayTest/Main.jack
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
62
projects/12/Keyboard.jack
Normal file
62
projects/12/Keyboard.jack
Normal file
@@ -0,0 +1,62 @@
|
||||
// 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 {
|
||||
|
||||
/** Initializes the keyboard. */
|
||||
function void init() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
}
|
||||
}
|
||||
196
projects/12/KeyboardTest/Keyboard.jack
Normal file
196
projects/12/KeyboardTest/Keyboard.jack
Normal file
@@ -0,0 +1,196 @@
|
||||
// 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 {
|
||||
|
||||
/** Initializes the keyboard. */
|
||||
function void init() {
|
||||
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() {
|
||||
var char value;
|
||||
let value = Memory.peek(24576);
|
||||
|
||||
if (value = 128) {
|
||||
return String.newLine();
|
||||
}
|
||||
|
||||
if (value = 129) {
|
||||
return String.backSpace();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 key, result;
|
||||
while (Keyboard.keyPressed() = 0) {}
|
||||
let key = Keyboard.keyPressed();
|
||||
while (~(Keyboard.keyPressed() = 0)) {}
|
||||
if (key = String.newLine()) {
|
||||
return key;
|
||||
}
|
||||
if (key = String.backSpace()) {
|
||||
return key;
|
||||
}
|
||||
do Output.printChar(key);
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
var char key, newline, backspace;
|
||||
var int i;
|
||||
let newline = String.newLine();
|
||||
let backspace = String.backSpace();
|
||||
let s = String.new(128);
|
||||
let key = 0;
|
||||
|
||||
do Output.printString(message);
|
||||
let i = 0;
|
||||
while (~(key = newline)) {
|
||||
let key = Keyboard.readChar();
|
||||
if (key = newline) {
|
||||
do Output.println();
|
||||
return s;
|
||||
} else {
|
||||
if (key = backspace) {
|
||||
if (i > 0) {
|
||||
do s.eraseLastChar();
|
||||
do Output.backSpace();
|
||||
let i = i - 1;
|
||||
}
|
||||
} else {
|
||||
do s.appendChar(key);
|
||||
let i = i + 1;
|
||||
}
|
||||
}
|
||||
// Prevent out of bound error.
|
||||
if (i = 128) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function int textToInt(String s) {
|
||||
var int result, i, length, multiplier;
|
||||
var char c;
|
||||
var boolean isNegative, continue;
|
||||
let isNegative = false;
|
||||
let length = s.length();
|
||||
let i = 0;
|
||||
let result = 0;
|
||||
let multiplier = 1;
|
||||
|
||||
if (length = 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s.charAt(0) = 45) {
|
||||
let isNegative = true;
|
||||
}
|
||||
|
||||
let i = length;
|
||||
while (true) {
|
||||
let i = i - 1;
|
||||
let c = s.charAt(i);
|
||||
if ((s.charAt(i) > 47) & (s.charAt(i) < 58)) {
|
||||
let result = result + ((s.charAt(i) - 48) * multiplier);
|
||||
let multiplier = multiplier * 10;
|
||||
} else {
|
||||
// could raise exception here;
|
||||
}
|
||||
|
||||
if (isNegative) {
|
||||
if (i = 1) {
|
||||
return -result;
|
||||
}
|
||||
} else {
|
||||
if (i = 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 key, newline, backspace;
|
||||
var int i;
|
||||
let newline = String.newLine();
|
||||
let backspace = String.backSpace();
|
||||
let s = String.new(128);
|
||||
let key = 0;
|
||||
|
||||
do Output.printString(message);
|
||||
let i = 0;
|
||||
while (~(key = newline)) {
|
||||
let key = Keyboard.readChar();
|
||||
if (key = newline) {
|
||||
do Output.println();
|
||||
} else {
|
||||
if (key = backspace) {
|
||||
if (i > 0) {
|
||||
do s.eraseLastChar();
|
||||
do Output.backSpace();
|
||||
let i = i - 1;
|
||||
}
|
||||
} else {
|
||||
do s.appendChar(key);
|
||||
let i = i + 1;
|
||||
}
|
||||
}
|
||||
// Prevent out of bound error.
|
||||
if (i = 128) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
let i = Keyboard.textToInt(s);
|
||||
do s.dispose();
|
||||
return i;
|
||||
}
|
||||
}
|
||||
BIN
projects/12/KeyboardTest/KeyboardTestOutput.gif
Normal file
BIN
projects/12/KeyboardTest/KeyboardTestOutput.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
93
projects/12/KeyboardTest/Main.jack
Normal file
93
projects/12/KeyboardTest/Main.jack
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
47
projects/12/Math.jack
Normal file
47
projects/12/Math.jack
Normal file
@@ -0,0 +1,47 @@
|
||||
// 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 {
|
||||
|
||||
/** Initializes the library. */
|
||||
function void init() {
|
||||
}
|
||||
|
||||
/** Returns the absolute value of x. */
|
||||
function int abs(int 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) {
|
||||
}
|
||||
|
||||
/** 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) {
|
||||
}
|
||||
|
||||
/** Returns the integer part of the square root of x. */
|
||||
function int sqrt(int x) {
|
||||
}
|
||||
|
||||
/** Returns the greater number. */
|
||||
function int max(int a, int b) {
|
||||
}
|
||||
|
||||
/** Returns the smaller number. */
|
||||
function int min(int a, int b) {
|
||||
}
|
||||
}
|
||||
35
projects/12/MathTest/Main.jack
Normal file
35
projects/12/MathTest/Main.jack
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
133
projects/12/MathTest/Math.jack
Normal file
133
projects/12/MathTest/Math.jack
Normal file
@@ -0,0 +1,133 @@
|
||||
// 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 {
|
||||
|
||||
/** Initializes the library. */
|
||||
function void init() {
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the absolute value of x. */
|
||||
function int abs(int x) {
|
||||
if (x < 0) {
|
||||
let x = -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;
|
||||
var int i;
|
||||
var int mask;
|
||||
var int xShifted;
|
||||
|
||||
let sum = 0;
|
||||
let i = 0;
|
||||
let mask = 1;
|
||||
let xShifted = x;
|
||||
|
||||
if (x = 1) {
|
||||
return y;
|
||||
}
|
||||
|
||||
if (y = 1) {
|
||||
return x;
|
||||
}
|
||||
|
||||
while (i < 16) { // 16 because we got a 16 bit architecture
|
||||
if (y & mask) {
|
||||
let sum = sum + xShifted;
|
||||
}
|
||||
let xShifted = xShifted + xShifted; // xShifted << 2;
|
||||
let mask = mask + mask; // mask << 2;
|
||||
let i = i + 1;
|
||||
}
|
||||
|
||||
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;
|
||||
var int sign;
|
||||
|
||||
let sign = 1;
|
||||
|
||||
if (x < 0) {
|
||||
let x = -x;
|
||||
let sign = -sign;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
let y = -y;
|
||||
let sign = -sign;
|
||||
}
|
||||
|
||||
if (y > x) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let q = x / (y + y);
|
||||
|
||||
if ((x - (2 * q * y)) < y) {
|
||||
return (q + q) * sign;
|
||||
} else {
|
||||
return (q + q + 1) * sign;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the integer part of the square root of x. */
|
||||
function int sqrt(int x) {
|
||||
var int y;
|
||||
var int p;
|
||||
var int s;
|
||||
var int s2;
|
||||
|
||||
let y = 0;
|
||||
let p = 128; // 2^7
|
||||
|
||||
while (p > 0) {
|
||||
let s = y + p;
|
||||
let s2 = s * s;
|
||||
if ((s2 - 1) < x) {
|
||||
if (s2 > 0) {
|
||||
let y = s;
|
||||
}
|
||||
}
|
||||
let p = p / 2; // p >> 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;
|
||||
}
|
||||
}
|
||||
2
projects/12/MathTest/MathTest.cmp
Normal file
2
projects/12/MathTest/MathTest.cmp
Normal file
@@ -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 |
|
||||
15
projects/12/MathTest/MathTest.tst
Normal file
15
projects/12/MathTest/MathTest.tst
Normal file
@@ -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 1000000 {
|
||||
vmstep;
|
||||
}
|
||||
|
||||
output;
|
||||
34
projects/12/Memory.jack
Normal file
34
projects/12/Memory.jack
Normal file
@@ -0,0 +1,34 @@
|
||||
// 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 {
|
||||
|
||||
/** Initializes the class. */
|
||||
function void init() {
|
||||
}
|
||||
|
||||
/** Returns the RAM value at the given address. */
|
||||
function int peek(int address) {
|
||||
}
|
||||
|
||||
/** Sets the RAM value at the given address to the given value. */
|
||||
function void poke(int address, int value) {
|
||||
}
|
||||
|
||||
/** Finds an available RAM block of the given size and returns
|
||||
* a reference to its base address. */
|
||||
function int alloc(int size) {
|
||||
}
|
||||
|
||||
/** De-allocates the given object (cast as an array) by making
|
||||
* it available for future allocations. */
|
||||
function void deAlloc(Array o) {
|
||||
}
|
||||
}
|
||||
42
projects/12/MemoryTest/Main.jack
Normal file
42
projects/12/MemoryTest/Main.jack
Normal file
@@ -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/MemoryTest/Main.jack
|
||||
|
||||
/** Test program for the OS Memory class. */
|
||||
class Main {
|
||||
|
||||
/** Performs various memory manipulations. */
|
||||
function void main() {
|
||||
var int temp;
|
||||
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 b = Array.new(3);
|
||||
let b[1] = a[2] - 100;
|
||||
do Memory.poke(8003, b[1]); // RAM[8003] = 122
|
||||
|
||||
let c = Array.new(500);
|
||||
let c[499] = a[2] - b[1];
|
||||
do Memory.poke(8004, c[499]); // RAM[8004] = 100
|
||||
|
||||
do a.dispose(); // uses Memory.deAlloc
|
||||
do b.dispose();
|
||||
|
||||
let b = Array.new(3);
|
||||
let b[0] = c[499] - 90;
|
||||
do Memory.poke(8005, b[0]); // RAM[8005] = 10
|
||||
|
||||
do c.dispose();
|
||||
do b.dispose();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
120
projects/12/MemoryTest/Memory.jack
Normal file
120
projects/12/MemoryTest/Memory.jack
Normal file
@@ -0,0 +1,120 @@
|
||||
// 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 ram;
|
||||
static Array heap;
|
||||
static Array freeList;
|
||||
|
||||
/** Initializes the class. */
|
||||
function void init() {
|
||||
let ram = 0;
|
||||
let heap = 2048;
|
||||
let freeList = heap;
|
||||
let freeList[0] = 0; // next
|
||||
let freeList[1] = 14334; // length
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the RAM value at the given address. */
|
||||
function int peek(int address) {
|
||||
return ram[address];
|
||||
}
|
||||
|
||||
/** Sets the RAM value at the given address to the given value. */
|
||||
function void poke(int address, int value) {
|
||||
let ram[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 previousBlock;
|
||||
var Array currentBlock;
|
||||
var Array resultBlock;
|
||||
var int currentBlockSize;
|
||||
var int remainingSize;
|
||||
var int currentBlockNext;
|
||||
|
||||
if (freeList = 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XXX: I am not happy with having the whole code duplicated just because
|
||||
// we have the "special case" that we select the first block.
|
||||
|
||||
// Using the first block is a special case, because we have to
|
||||
// update freeList instead of simply taking the block out of the list
|
||||
// by doing `let previousBlock.next = currentBlock.next`.
|
||||
let currentBlockSize = freeList[1];
|
||||
if (currentBlockSize > size) {
|
||||
let remainingSize = currentBlockSize - size;
|
||||
let resultBlock = freeList;
|
||||
if (remainingSize < 4) {
|
||||
// If remainingSize is smaller than 4 it does not make sense to split
|
||||
// the block. Just return it as a whole.
|
||||
let freeList = freeList[0]; // point to freeList.next
|
||||
} else {
|
||||
// If remainingSize is big enough we split the block. In that case
|
||||
// we have to update the size of the block we return as well as
|
||||
// the block (aka the remainder of the current block).
|
||||
let resultBlock[1] = size;
|
||||
let freeList = resultBlock + 2 + size;
|
||||
let freeList[0] = resultBlock[0];
|
||||
let freeList[1] = currentBlockSize - size - 2;
|
||||
}
|
||||
return resultBlock + 2;
|
||||
}
|
||||
|
||||
let previousBlock = freeList;
|
||||
// The following excludes the first block which is what we want
|
||||
// because we handled it separately before.
|
||||
while (~(previousBlock[0] = 0)) {
|
||||
let currentBlock = previousBlock[0];
|
||||
let currentBlockSize = currentBlock[1];
|
||||
if (currentBlockSize > size) {
|
||||
let resultBlock = currentBlock;
|
||||
let remainingSize = currentBlockSize - size;
|
||||
if (remainingSize < 4) {
|
||||
let previousBlock[0] = resultBlock[0];
|
||||
} else {
|
||||
let resultBlock[1] = size;
|
||||
let currentBlock = resultBlock + 2 + size;
|
||||
let currentBlock[0] = resultBlock[0];
|
||||
let currentBlock[1] = currentBlockSize - size - 2;
|
||||
let previousBlock[0] = currentBlock;
|
||||
}
|
||||
return resultBlock;
|
||||
} else {
|
||||
let previousBlock = currentBlock;
|
||||
}
|
||||
}
|
||||
|
||||
// Not enough heap available. Call defragment and try again.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** De-allocates the given object (cast as an array) by making
|
||||
* it available for future allocations. */
|
||||
function void deAlloc(Array o) {
|
||||
var Array currentBlock;
|
||||
if (freeList = 0) {
|
||||
let freeList = o - 2;
|
||||
}
|
||||
let currentBlock = freeList;
|
||||
while (~(currentBlock[0] = 0)) {
|
||||
let currentBlock = currentBlock[0];
|
||||
}
|
||||
|
||||
let currentBlock[0] = o - 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
2
projects/12/MemoryTest/MemoryTest.cmp
Normal file
2
projects/12/MemoryTest/MemoryTest.cmp
Normal file
@@ -0,0 +1,2 @@
|
||||
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|RAM[8004]|RAM[8005]|
|
||||
| 333 | 334 | 222 | 122 | 100 | 10 |
|
||||
15
projects/12/MemoryTest/MemoryTest.tst
Normal file
15
projects/12/MemoryTest/MemoryTest.tst
Normal file
@@ -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;
|
||||
203
projects/12/Output.jack
Normal file
203
projects/12/Output.jack
Normal file
@@ -0,0 +1,203 @@
|
||||
// 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;
|
||||
|
||||
/** Initializes the screen, and locates the cursor at the screen's top-left. */
|
||||
function void init() {
|
||||
}
|
||||
|
||||
// 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,0,0,0,0,0,0,0,0,0,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) {
|
||||
}
|
||||
|
||||
/** Displays the given character at the cursor location,
|
||||
* and advances the cursor one column forward. */
|
||||
function void printChar(char c) {
|
||||
}
|
||||
|
||||
/** displays the given string starting at the cursor location,
|
||||
* and advances the cursor appropriately. */
|
||||
function void printString(String s) {
|
||||
}
|
||||
|
||||
/** Displays the given integer starting at the cursor location,
|
||||
* and advances the cursor appropriately. */
|
||||
function void printInt(int i) {
|
||||
}
|
||||
|
||||
/** Advances the cursor to the beginning of the next line. */
|
||||
function void println() {
|
||||
}
|
||||
|
||||
/** Moves the cursor one column back. */
|
||||
function void backSpace() {
|
||||
}
|
||||
}
|
||||
42
projects/12/OutputTest/Main.jack
Normal file
42
projects/12/OutputTest/Main.jack
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
317
projects/12/OutputTest/Output.jack
Normal file
317
projects/12/OutputTest/Output.jack
Normal file
@@ -0,0 +1,317 @@
|
||||
// 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 currentColumn;
|
||||
static int currentRow;
|
||||
|
||||
/** Initializes the screen, and locates the cursor at the screen's top-left. */
|
||||
function void init() {
|
||||
do Screen.clearScreen();
|
||||
do Output.initMap();
|
||||
let currentColumn = 0;
|
||||
let currentRow = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
function int modulo(int a, int b) {
|
||||
var int d;
|
||||
let d = a / b;
|
||||
return a - (d * b);
|
||||
}
|
||||
|
||||
// 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
|
||||
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) {
|
||||
let currentRow = i;
|
||||
let currentColumn = j;
|
||||
do Output.printChar(32);
|
||||
let currentRow = i;
|
||||
let currentColumn = j;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given character at the cursor location,
|
||||
* and advances the cursor one column forward. */
|
||||
function void printChar(char c) {
|
||||
var Array m;
|
||||
var int i, address, value, currentCharRow, higherByte;
|
||||
|
||||
let m = Output.getMap(c);
|
||||
let address = 16384 + (32 * currentRow * 11) + ((currentColumn * 8) / 16);
|
||||
let higherByte = Output.modulo(currentColumn, 2);
|
||||
|
||||
let i = 0;
|
||||
while (i < 11) {
|
||||
let value = Memory.peek(address);
|
||||
let currentCharRow = m[i];
|
||||
if (higherByte = 1) {
|
||||
let currentCharRow = currentCharRow * 256; // x << 8;
|
||||
let value = currentCharRow | (value & 255); // 255 = 0x00ff
|
||||
} else {
|
||||
let value = (value & (-256)) | (currentCharRow); // -256 = 0xff00
|
||||
}
|
||||
do Memory.poke(address, value);
|
||||
let address = address + 32;
|
||||
let i = i + 1;
|
||||
}
|
||||
|
||||
if (currentColumn = 63) {
|
||||
if (currentRow = 22) {
|
||||
let currentRow = 0;
|
||||
let currentColumn = 0;
|
||||
} else {
|
||||
let currentColumn = 0;
|
||||
let currentRow = currentRow + 1;
|
||||
}
|
||||
} else {
|
||||
let currentColumn = currentColumn + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** displays the given string starting at the cursor location,
|
||||
* and advances the cursor appropriately. */
|
||||
function void printString(String s) {
|
||||
var int stringLength, i;
|
||||
let stringLength = s.length();
|
||||
let i = 0;
|
||||
while (i < stringLength) {
|
||||
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 int digit, divisor;
|
||||
var boolean firstDigitPrinted;
|
||||
let divisor = 10000;
|
||||
let firstDigitPrinted = false;
|
||||
|
||||
if (i = 0) {
|
||||
do Output.printChar(48 + 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (i < 0) {
|
||||
do Output.printChar(45); // 45 = '-'
|
||||
let i = (~i) + 1;
|
||||
}
|
||||
|
||||
while (~(divisor = 0)) {
|
||||
let digit = i / divisor;
|
||||
|
||||
if (digit = 0) {
|
||||
if (firstDigitPrinted) {
|
||||
do Output.printChar(48 + 0);
|
||||
}
|
||||
} else {
|
||||
do Output.printChar(48 + digit);
|
||||
let firstDigitPrinted = true;
|
||||
}
|
||||
|
||||
let i = i - (digit * divisor);
|
||||
let divisor = divisor / 10;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Advances the cursor to the beginning of the next line. */
|
||||
function void println() {
|
||||
if (currentRow = 22) {
|
||||
let currentRow = 0;
|
||||
} else {
|
||||
let currentRow = currentRow + 1;
|
||||
}
|
||||
let currentColumn = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the cursor one column back. */
|
||||
function void backSpace() {
|
||||
var int newRow, newColumn;
|
||||
|
||||
if (currentColumn = 0) {
|
||||
if (currentRow = 0) {
|
||||
let newRow = 22;
|
||||
let newColumn = 63;
|
||||
} else {
|
||||
let newRow = currentRow - 1;
|
||||
let newColumn = 63;
|
||||
}
|
||||
} else {
|
||||
let newRow = currentRow;
|
||||
let newColumn = currentColumn - 1;
|
||||
}
|
||||
do Output.moveCursor(newRow, newColumn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
BIN
projects/12/OutputTest/OutputTestOutput.gif
Normal file
BIN
projects/12/OutputTest/OutputTestOutput.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
43
projects/12/Screen.jack
Normal file
43
projects/12/Screen.jack
Normal file
@@ -0,0 +1,43 @@
|
||||
// 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 512 rows (indexed 0..511, top to bottom)
|
||||
* of 256 pixels each (indexed 0..255, left to right). The top left pixel on
|
||||
* the screen is indexed (0,0).
|
||||
*/
|
||||
class Screen {
|
||||
|
||||
/** Initializes the Screen. */
|
||||
function void init() {
|
||||
}
|
||||
|
||||
/** Erases the entire screen. */
|
||||
function void clearScreen() {
|
||||
}
|
||||
|
||||
/** 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) {
|
||||
}
|
||||
|
||||
/** Draws the (x,y) pixel, using the current color. */
|
||||
function void drawPixel(int x, int y) {
|
||||
}
|
||||
|
||||
/** 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) {
|
||||
}
|
||||
|
||||
/** 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) {
|
||||
}
|
||||
|
||||
/** Draws a filled circle of radius r<=181 around (x,y), using the current color. */
|
||||
function void drawCircle(int x, int y, int r) {
|
||||
}
|
||||
}
|
||||
36
projects/12/ScreenTest/Main.jack
Normal file
36
projects/12/ScreenTest/Main.jack
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
178
projects/12/ScreenTest/Screen.jack
Normal file
178
projects/12/ScreenTest/Screen.jack
Normal file
@@ -0,0 +1,178 @@
|
||||
// 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 512 rows (indexed 0..511, top to bottom)
|
||||
* of 256 pixels each (indexed 0..255, left to right). The top left pixel on
|
||||
* the screen is indexed (0,0).
|
||||
*/
|
||||
class Screen {
|
||||
|
||||
static boolean color;
|
||||
|
||||
/** Initializes the Screen. */
|
||||
function void init() {
|
||||
let color = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Erases the entire screen. */
|
||||
function void clearScreen() {
|
||||
var int i;
|
||||
var Array a;
|
||||
|
||||
let i = 0;
|
||||
let a = 16384;
|
||||
|
||||
while (i < 8192) {
|
||||
let a[i] = 0;
|
||||
let i = i + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function int modulo(int a, int b) {
|
||||
var int d;
|
||||
let d = a / b;
|
||||
return a - (d * b);
|
||||
}
|
||||
|
||||
/** 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 address;
|
||||
var int value;
|
||||
var int i;
|
||||
var int mask;
|
||||
var int inverseMask;
|
||||
var int pixel;
|
||||
|
||||
let pixel = Screen.modulo(x, 16);
|
||||
|
||||
let i = 0;
|
||||
let mask = 1;
|
||||
while (~(i = pixel)) {
|
||||
let mask = mask + mask;
|
||||
let i = i + 1;
|
||||
}
|
||||
let inverseMask = ~mask;
|
||||
|
||||
let address = 16384 + (32 * y) + (x / 16);
|
||||
let value = Memory.peek(address);
|
||||
|
||||
if (color) {
|
||||
let value = ((value & inverseMask) | ((-1) & mask)); // pixel gets set to 1
|
||||
} else {
|
||||
let value = (value & inverseMask); // pixel gets set to 0
|
||||
}
|
||||
do Memory.poke(address, 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 a, b, diff, dx, dy, xinc, yinc;
|
||||
var boolean continue;
|
||||
|
||||
let a = 0;
|
||||
let b = 0;
|
||||
let diff = 0;
|
||||
let dx = Math.abs(x2 - x1);
|
||||
let dy = Math.abs(y2 - y1);
|
||||
let continue = true;
|
||||
|
||||
if (x2 > x1) {
|
||||
let xinc = 1; // going from left to right;
|
||||
} else {
|
||||
let xinc = -1; // going from right to left;
|
||||
}
|
||||
|
||||
if (y2 > y1) {
|
||||
let yinc = 1; // going from top to bottom
|
||||
} else {
|
||||
let yinc = -1; // going from bottom to top
|
||||
}
|
||||
|
||||
// vertical line
|
||||
if (dx = 0) {
|
||||
while (~(y1 = y2)) {
|
||||
do Screen.drawPixel(x1, y1);
|
||||
let y1 = y1 + yinc;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// horizontal line
|
||||
if (dy = 0) {
|
||||
while (~(x1 = x2)) {
|
||||
do Screen.drawPixel(x1, y1);
|
||||
let x1 = x1 + xinc;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while (continue) {
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0) {
|
||||
let a = a + xinc;
|
||||
let diff = diff + dy;
|
||||
} else {
|
||||
let b = b + yinc;
|
||||
let diff = diff - dx;
|
||||
}
|
||||
|
||||
if ((x1 + a) = x2) {
|
||||
if ((y1 + b) = y2) {
|
||||
let continue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 yinc;
|
||||
if (y2 > y1) {
|
||||
let yinc = 1;
|
||||
} else {
|
||||
let yinc = -1;
|
||||
}
|
||||
|
||||
while (~(y1 = y2)) {
|
||||
do Screen.drawLine(x1, y1, x2, y1);
|
||||
let y1 = y1 + yinc;
|
||||
}
|
||||
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;
|
||||
var int halfSegment;
|
||||
let dy = -r;
|
||||
|
||||
if (r > 181) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (dy < (r + 1)) {
|
||||
let halfSegment = Math.sqrt((r * r) - (dy * dy));
|
||||
do Screen.drawLine(x - halfSegment, y + dy, x + halfSegment, y + dy);
|
||||
let dy = dy + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
BIN
projects/12/ScreenTest/ScreenTestOutput.gif
Normal file
BIN
projects/12/ScreenTest/ScreenTestOutput.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
64
projects/12/String.jack
Normal file
64
projects/12/String.jack
Normal file
@@ -0,0 +1,64 @@
|
||||
// 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 {
|
||||
|
||||
/** constructs a new empty string with a maximum length of maxLength
|
||||
* and initial length of 0. */
|
||||
constructor String new(int maxLength) {
|
||||
}
|
||||
|
||||
/** Disposes this string. */
|
||||
method void dispose() {
|
||||
}
|
||||
|
||||
/** Returns the current length of this string. */
|
||||
method int length() {
|
||||
}
|
||||
|
||||
/** Returns the character at the j-th location of this string. */
|
||||
method char charAt(int j) {
|
||||
}
|
||||
|
||||
/** Sets the character at the j-th location of this string to c. */
|
||||
method void setCharAt(int j, char c) {
|
||||
}
|
||||
|
||||
/** Appends c to this string's end and returns this string. */
|
||||
method String appendChar(char c) {
|
||||
}
|
||||
|
||||
/** Erases the last character from this string. */
|
||||
method void eraseLastChar() {
|
||||
}
|
||||
|
||||
/** Returns the integer value of this string,
|
||||
* until a non-digit character is detected. */
|
||||
method int intValue() {
|
||||
}
|
||||
|
||||
/** Sets this string to hold a representation of the given value. */
|
||||
method void setInt(int val) {
|
||||
}
|
||||
|
||||
/** Returns the new line character. */
|
||||
function char newLine() {
|
||||
}
|
||||
|
||||
/** Returns the backspace character. */
|
||||
function char backSpace() {
|
||||
}
|
||||
|
||||
/** Returns the double quote (") character. */
|
||||
function char doubleQuote() {
|
||||
}
|
||||
}
|
||||
83
projects/12/StringTest/Main.jack
Normal file
83
projects/12/StringTest/Main.jack
Normal file
@@ -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,appendChar: ");
|
||||
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;
|
||||
}
|
||||
}
|
||||
203
projects/12/StringTest/String.jack
Normal file
203
projects/12/StringTest/String.jack
Normal file
@@ -0,0 +1,203 @@
|
||||
// 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 int maxLength;
|
||||
field int length;
|
||||
field Array s;
|
||||
|
||||
/** constructs a new empty string with a maximum length of maxLength
|
||||
* and initial length of 0. */
|
||||
constructor String new(int maxStringLength) {
|
||||
let maxLength = maxStringLength;
|
||||
let length = 0;
|
||||
// Only allocate memory for positive length.
|
||||
if (maxLength > 0) {
|
||||
let s = Array.new(maxLength);
|
||||
} else {
|
||||
let s = 0;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Disposes this string. */
|
||||
method void dispose() {
|
||||
// Only deAlloc for positive length. We do not alloc memory in constructor
|
||||
// if length is not positive.
|
||||
if (~(s = 0)) {
|
||||
do s.dispose();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the current length of this string. */
|
||||
method int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Sets all fields to null and resets length. */
|
||||
method void clear() {
|
||||
var int i;
|
||||
let i = 0;
|
||||
|
||||
while (i < maxLength) {
|
||||
let s[i] = 0;
|
||||
let i = i + 1;
|
||||
}
|
||||
let length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the character at the j-th location of this string. */
|
||||
method char charAt(int j) {
|
||||
if (j < maxLength) {
|
||||
return s[j];
|
||||
}
|
||||
return 0; // Out-of-bounds access. Consider raising an error.
|
||||
}
|
||||
|
||||
/** Sets the character at the j-th location of this string to c. */
|
||||
method void setCharAt(int j, char c) {
|
||||
if (j < maxLength) {
|
||||
let s[j] = c;
|
||||
} else {
|
||||
// Out-of-bounds access. Consider raising an error.
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Appends c to this string's end and returns this string. */
|
||||
method String appendChar(char c) {
|
||||
if (length < maxLength) {
|
||||
let s[length] = c;
|
||||
let length = length + 1;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Erases the last character from this string. */
|
||||
method void eraseLastChar() {
|
||||
if (length > 0) {
|
||||
let length = length - 1;
|
||||
let s[length] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the integer value of this string,
|
||||
* until a non-digit character is detected. */
|
||||
method int intValue() {
|
||||
var int i, result, multiplier;
|
||||
var boolean isNegative, continue;
|
||||
var char c;
|
||||
let i = 0;
|
||||
let isNegative = false;
|
||||
|
||||
if (charAt(0) = 45) {
|
||||
let isNegative = true;
|
||||
let i = i + 1;
|
||||
}
|
||||
|
||||
// First iterate up to the highest numerical character.
|
||||
let continue = true;
|
||||
while (continue) {
|
||||
let c = charAt(i);
|
||||
if ((c > 47) & (c < 58)) {
|
||||
let i = i + 1;
|
||||
} else {
|
||||
let continue = false;
|
||||
}
|
||||
if (~(i < maxLength)) {
|
||||
let continue = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Then iterate backwards and add the values to result.
|
||||
// Checking if we are within the range allows us to not
|
||||
// worry about a potential negative sign.
|
||||
let continue = true;
|
||||
let multiplier = 1;
|
||||
let i = i - 1;
|
||||
while (continue) {
|
||||
let c = charAt(i);
|
||||
if ((c > 47) & (c < 58)) {
|
||||
let result = result + ((c - 48) * multiplier);
|
||||
let multiplier = multiplier * 10;
|
||||
} else {
|
||||
let continue = false;
|
||||
}
|
||||
|
||||
if (i = 0) {
|
||||
let continue = false;
|
||||
}
|
||||
let i = i - 1;
|
||||
}
|
||||
|
||||
if (isNegative) {
|
||||
let result = -result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Sets this string to hold a representation of the given value. */
|
||||
method void setInt(int val) {
|
||||
var int digit, divisor;
|
||||
var boolean firstDigitPrinted;
|
||||
let divisor = 10000;
|
||||
let firstDigitPrinted = false;
|
||||
do clear();
|
||||
|
||||
if (val = 0) {
|
||||
do appendChar(48); // 0
|
||||
return;
|
||||
}
|
||||
|
||||
if (val < 0) {
|
||||
do appendChar(45); // 45 = '-'
|
||||
let val = (~val) + 1;
|
||||
}
|
||||
|
||||
while (~(divisor = 0)) {
|
||||
let digit = val / divisor;
|
||||
|
||||
if (digit = 0) {
|
||||
if (firstDigitPrinted) {
|
||||
do appendChar(48 + 0);
|
||||
}
|
||||
} else {
|
||||
do appendChar(48 + digit);
|
||||
let firstDigitPrinted = true;
|
||||
}
|
||||
|
||||
let val = val - (digit * divisor);
|
||||
let divisor = divisor / 10;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
BIN
projects/12/StringTest/StringTestOutput.gif
Normal file
BIN
projects/12/StringTest/StringTestOutput.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.9 KiB |
27
projects/12/Sys.jack
Normal file
27
projects/12/Sys.jack
Normal file
@@ -0,0 +1,27 @@
|
||||
// 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() {
|
||||
}
|
||||
|
||||
/** Halts the program execution. */
|
||||
function void halt() {
|
||||
}
|
||||
|
||||
/** Waits approximately duration milliseconds and returns. */
|
||||
function void wait(int duration) {
|
||||
}
|
||||
|
||||
/** Displays the given error code in the form "ERR<errorCode>",
|
||||
* and halts the program's execution. */
|
||||
function void error(int errorCode) {
|
||||
}
|
||||
}
|
||||
31
projects/12/SysTest/Main.jack
Normal file
31
projects/12/SysTest/Main.jack
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
52
projects/12/SysTest/Sys.jack
Normal file
52
projects/12/SysTest/Sys.jack
Normal file
@@ -0,0 +1,52 @@
|
||||
// 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 Memory.init();
|
||||
do Screen.init();
|
||||
do Keyboard.init();
|
||||
do Output.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, j;
|
||||
let i = 0;
|
||||
while (i < duration) {
|
||||
let i = i + 1;
|
||||
let j = 0;
|
||||
while (j < 50) {
|
||||
let j = j + 1;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given error code in the form "ERR<errorCode>",
|
||||
* and halts the program's execution. */
|
||||
function void error(int errorCode) {
|
||||
do Output.printString("ERR<");
|
||||
do Output.printInt(errorCode);
|
||||
do Output.printString(">");
|
||||
do Sys.halt();
|
||||
return;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user