diff options
| -rw-r--r-- | projects/12/Math.jack | 98 | ||||
| -rw-r--r-- | projects/12/MathTest/Main.vm | 162 | ||||
| -rw-r--r-- | projects/12/MathTest/Math.jack | 146 | ||||
| -rw-r--r-- | projects/12/MathTest/Math.vm | 446 | ||||
| -rw-r--r-- | projects/12/MathTest/MathTest.out | 2 | 
5 files changed, 854 insertions, 0 deletions
diff --git a/projects/12/Math.jack b/projects/12/Math.jack index a57f023..61e09fc 100644 --- a/projects/12/Math.jack +++ b/projects/12/Math.jack @@ -8,13 +8,33 @@   * Note: Jack compilers implement multiplication and division using OS method calls.
   */
  class Math {
 +    static Array twoToThe;
      /** Initializes the library. */
      function void init() {
 +        var int i, x;
 +        let x = 1;
 +        let i = 0;
 +        let twoToThe = Array.new(16);
 +        while (i < 16){
 +            let twoToThe[i] = x;
 +            let x = x + x;
 +            let i = i + 1;
 +        }
 +        return;
 +    }
 +
 +    function boolean bit(int x, int i) {
 +        return ~(x & twoToThe[i] = 0);
      }
      /** Returns the absolute value of x. */
      function int abs(int x) {
 +        if (x > 0){
 +            return x;
 +        } else {
 +            return -x;
 +        }
      }
      /** Returns the product of x and y. 
 @@ -23,6 +43,18 @@ class Math {       *  the Jack expressions x*y and multiply(x,y) return the same value.
       */
      function int multiply(int x, int y) {
 +        var int z, res, shiftedX, i;
 +        let shiftedX = x;
 +        let i = 0;
 +        let res = 0;
 +        while ((twoToThe[i] > x) & (i < 16)) {
 +            if (Math.bit(y, i)){
 +                let res = res + shiftedX;
 +            }
 +            let shiftedX = shiftedX + shiftedX;
 +            let i = i + 1;
 +        }
 +        return res;
      }
      /** Returns the integer part of x/y.
 @@ -31,17 +63,83 @@ class Math {       *  the Jack expressions x/y and divide(x,y) return the same value.
       */
      function int divide(int x, int y) {
 +        var int ax, ay;
 +        if (x > 0) {
 +            if (y > 0) {
 +                return Math.divide1(x, y);
 +            } else {
 +                return -Math.divide1(x, -y);
 +            }
 +        } else {
 +            if (y > 0) {
 +                return -Math.divide1(-x, y);
 +            } else {
 +                return Math.divide1(-x, -y);
 +            }
 +        }
 +    }
 +
 +    function int divide1(int x, int y) {
 +        var int q;
 +        if (y = 0) {
 +            do Output.printString("Error: division by zero.");
 +            do Sys.error(0);
 +        }
 +        if ((y > x) | (y < 0)) {
 +            return 0;
 +        }
 +        let q = Math.divide1(x, y * 2);
 +        if (x - (2 * q * y) < y) {
 +            return 2 * q;
 +        } else {
 +            return 2 * q + 1;
 +        }
 +    }
 +
 +    function int length(int x){
 +        var int n;
 +        let n = 14;
 +        while (twoToThe[n] > x){
 +            let n = n - 1;
 +        }
 +        return n;
      }
      /** Returns the integer part of the square root of x. */
      function int sqrt(int x) {
 +        var int y, k, z, w;
 +        if (x < 0) {
 +            do Output.printString("Error: square rooting a negative number.");
 +            do Sys.error(0);
 +        }
 +        let k = Math.length(x) / 2;
 +        let y = 0;
 +        while (~(k < 0)) {
 +            let z = y + twoToThe[k];
 +            let w = z * z;
 +            if ((w < x) & (w > 0)) {
 +                let y = z;
 +            }
 +            let k = k - 1;
 +        }
 +        return y;
      }
      /** Returns the greater number. */
      function int max(int a, int b) {
 +        if (a > b) {
 +            return a;
 +        } else {
 +            return b;
 +        }
      }
      /** Returns the smaller number. */
      function int min(int a, int b) {
 +        if (a < b) {
 +            return a;
 +        } else {
 +            return b;
 +        }
      }
  }
 diff --git a/projects/12/MathTest/Main.vm b/projects/12/MathTest/Main.vm new file mode 100644 index 0000000..025f20c --- /dev/null +++ b/projects/12/MathTest/Main.vm @@ -0,0 +1,162 @@ +function Main.main 1 +push constant 8000 +pop local 0 +push constant 0 +push local 0 +add +push constant 2 +push constant 3 +call Math.multiply 2 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 1 +push local 0 +add +push constant 0 +push local 0 +add +pop pointer 1 +push that 0 +push constant 30 +neg +call Math.multiply 2 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 2 +push local 0 +add +push constant 1 +push local 0 +add +pop pointer 1 +push that 0 +push constant 100 +call Math.multiply 2 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 3 +push local 0 +add +push constant 1 +push constant 2 +push local 0 +add +pop pointer 1 +push that 0 +call Math.multiply 2 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 4 +push local 0 +add +push constant 3 +push local 0 +add +pop pointer 1 +push that 0 +push constant 0 +call Math.multiply 2 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 5 +push local 0 +add +push constant 9 +push constant 3 +call Math.divide 2 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 6 +push local 0 +add +push constant 18000 +neg +push constant 6 +call Math.divide 2 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 7 +push local 0 +add +push constant 32766 +push constant 32767 +neg +call Math.divide 2 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 8 +push local 0 +add +push constant 9 +call Math.sqrt 1 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 9 +push local 0 +add +push constant 32767 +call Math.sqrt 1 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 10 +push local 0 +add +push constant 345 +push constant 123 +call Math.min 2 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 11 +push local 0 +add +push constant 123 +push constant 345 +neg +call Math.max 2 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 12 +push local 0 +add +push constant 27 +call Math.abs 1 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 13 +push local 0 +add +push constant 32767 +neg +call Math.abs 1 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push constant 0 +return diff --git a/projects/12/MathTest/Math.jack b/projects/12/MathTest/Math.jack new file mode 100644 index 0000000..6bac42e --- /dev/null +++ b/projects/12/MathTest/Math.jack @@ -0,0 +1,146 @@ +// 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 twoToThe;
 +
 +    /** Initializes the library. */
 +    function void init() {
 +        var int i, x;
 +        let x = 1;
 +        let i = 0;
 +        let twoToThe = Array.new(16);
 +        while (i < 16){
 +            let twoToThe[i] = x;
 +            let x = x + x;
 +            let i = i + 1;
 +        }
 +        return;
 +    }
 +
 +    function boolean bit(int x, int i) {
 +        return ~(x & twoToThe[i] = 0);
 +    }
 +
 +    /** Returns the absolute value of x. */
 +    function int abs(int x) {
 +        if (x > 0){
 +            return x;
 +        } else {
 +            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 res, shiftedX, i;
 +        let shiftedX = x;
 +        let i = 0;
 +        let res = 0;
 +        //while ((~(twoToThe[i] > y)) & (i < 16)) {
 +        while (i < 16) {
 +            if (Math.bit(y, i)){
 +                let res = res + shiftedX;
 +            }
 +            let shiftedX = shiftedX + shiftedX;
 +            let i = i + 1;
 +        }
 +        return res;
 +    }
 +
 +    /** 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 ax, ay;
 +        if (x > 0) {
 +            if (y > 0) {
 +                return Math.divide1(x, y);
 +            } else {
 +                return -Math.divide1(x, -y);
 +            }
 +        } else {
 +            if (y > 0) {
 +                return -Math.divide1(-x, y);
 +            } else {
 +                return Math.divide1(-x, -y);
 +            }
 +        }
 +    }
 +
 +    function int divide1(int x, int y) {
 +        var int q;
 +        if (y = 0) {
 +            do Output.printString("Error: division by zero.");
 +            do Sys.error(0);
 +        }
 +        if ((y > x) | (y < 0)) {
 +            return 0;
 +        }
 +        let q = Math.divide1(x, y * 2);
 +        if (x - (2 * q * y) < y) {
 +            return 2 * q;
 +        } else {
 +            return 2 * q + 1;
 +        }
 +    }
 +
 +    function int length(int x){
 +        var int n;
 +        let n = 14;
 +        while (twoToThe[n] > x){
 +            let n = n - 1;
 +        }
 +        return n;
 +    }
 +
 +    /** Returns the integer part of the square root of x. */
 +    function int sqrt(int x) {
 +        var int y, k, z, w;
 +        if (x < 0) {
 +            do Output.printString("Error: square rooting a negative number.");
 +            do Sys.error(0);
 +        }
 +        let k = Math.length(x) / 2;
 +        let y = 0;
 +        while (~(k < 0)) {
 +            let z = y + twoToThe[k];
 +            let w = z * z;
 +            if ((~(w > x)) & (w > 0)) {
 +                let y = z;
 +            }
 +            let k = k - 1;
 +        }
 +        return y;
 +    }
 +
 +    /** Returns the greater number. */
 +    function int max(int a, int b) {
 +        if (a > b) {
 +            return a;
 +        } else {
 +            return b;
 +        }
 +    }
 +
 +    /** Returns the smaller number. */
 +    function int min(int a, int b) {
 +        if (a < b) {
 +            return a;
 +        } else {
 +            return b;
 +        }
 +    }
 +}
 diff --git a/projects/12/MathTest/Math.vm b/projects/12/MathTest/Math.vm new file mode 100644 index 0000000..dad8ff5 --- /dev/null +++ b/projects/12/MathTest/Math.vm @@ -0,0 +1,446 @@ +function Math.init 2 +push constant 1 +pop local 1 +push constant 0 +pop local 0 +push constant 16 +call Array.new 1 +pop static 0 +label WHILE_EXP0 +push local 0 +push constant 16 +lt +not +if-goto WHILE_END0 +push local 0 +push static 0 +add +push local 1 +pop temp 0 +pop pointer 1 +push temp 0 +pop that 0 +push local 1 +push local 1 +add +pop local 1 +push local 0 +push constant 1 +add +pop local 0 +goto WHILE_EXP0 +label WHILE_END0 +push constant 0 +return +function Math.bit 0 +push argument 0 +push argument 1 +push static 0 +add +pop pointer 1 +push that 0 +and +push constant 0 +eq +not +return +function Math.abs 0 +push argument 0 +push constant 0 +gt +if-goto IF_TRUE0 +goto IF_FALSE0 +label IF_TRUE0 +push argument 0 +return +goto IF_END0 +label IF_FALSE0 +push argument 0 +neg +return +label IF_END0 +function Math.multiply 3 +push argument 0 +pop local 1 +push constant 0 +pop local 2 +push constant 0 +pop local 0 +label WHILE_EXP0 +push local 2 +push constant 16 +lt +not +if-goto WHILE_END0 +push argument 1 +push local 2 +call Math.bit 2 +if-goto IF_TRUE0 +goto IF_FALSE0 +label IF_TRUE0 +push local 0 +push local 1 +add +pop local 0 +label IF_FALSE0 +push local 1 +push local 1 +add +pop local 1 +push local 2 +push constant 1 +add +pop local 2 +goto WHILE_EXP0 +label WHILE_END0 +push local 0 +return +function Math.divide 2 +push argument 0 +push constant 0 +gt +if-goto IF_TRUE0 +goto IF_FALSE0 +label IF_TRUE0 +push argument 1 +push constant 0 +gt +if-goto IF_TRUE1 +goto IF_FALSE1 +label IF_TRUE1 +push argument 0 +push argument 1 +call Math.divide1 2 +return +goto IF_END1 +label IF_FALSE1 +push argument 0 +push argument 1 +neg +call Math.divide1 2 +neg +return +label IF_END1 +goto IF_END0 +label IF_FALSE0 +push argument 1 +push constant 0 +gt +if-goto IF_TRUE2 +goto IF_FALSE2 +label IF_TRUE2 +push argument 0 +neg +push argument 1 +call Math.divide1 2 +neg +return +goto IF_END2 +label IF_FALSE2 +push argument 0 +neg +push argument 1 +neg +call Math.divide1 2 +return +label IF_END2 +label IF_END0 +function Math.divide1 1 +push argument 1 +push constant 0 +eq +if-goto IF_TRUE0 +goto IF_FALSE0 +label IF_TRUE0 +push constant 24 +call String.new 1 +push constant 69 +call String.appendChar 2 +push constant 114 +call String.appendChar 2 +push constant 114 +call String.appendChar 2 +push constant 111 +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 +push constant 100 +call String.appendChar 2 +push constant 105 +call String.appendChar 2 +push constant 118 +call String.appendChar 2 +push constant 105 +call String.appendChar 2 +push constant 115 +call String.appendChar 2 +push constant 105 +call String.appendChar 2 +push constant 111 +call String.appendChar 2 +push constant 110 +call String.appendChar 2 +push constant 32 +call String.appendChar 2 +push constant 98 +call String.appendChar 2 +push constant 121 +call String.appendChar 2 +push constant 32 +call String.appendChar 2 +push constant 122 +call String.appendChar 2 +push constant 101 +call String.appendChar 2 +push constant 114 +call String.appendChar 2 +push constant 111 +call String.appendChar 2 +push constant 46 +call String.appendChar 2 +call Output.printString 1 +pop temp 0 +push constant 0 +call Sys.error 1 +pop temp 0 +label IF_FALSE0 +push argument 1 +push argument 0 +gt +push argument 1 +push constant 0 +lt +or +if-goto IF_TRUE1 +goto IF_FALSE1 +label IF_TRUE1 +push constant 0 +return +label IF_FALSE1 +push argument 0 +push argument 1 +push constant 2 +call Math.multiply 2 +call Math.divide1 2 +pop local 0 +push argument 0 +push constant 2 +push local 0 +call Math.multiply 2 +push argument 1 +call Math.multiply 2 +sub +push argument 1 +lt +if-goto IF_TRUE2 +goto IF_FALSE2 +label IF_TRUE2 +push constant 2 +push local 0 +call Math.multiply 2 +return +goto IF_END2 +label IF_FALSE2 +push constant 2 +push local 0 +call Math.multiply 2 +push constant 1 +add +return +label IF_END2 +function Math.length 1 +push constant 14 +pop local 0 +label WHILE_EXP0 +push local 0 +push static 0 +add +pop pointer 1 +push that 0 +push argument 0 +gt +not +if-goto WHILE_END0 +push local 0 +push constant 1 +sub +pop local 0 +goto WHILE_EXP0 +label WHILE_END0 +push local 0 +return +function Math.sqrt 4 +push argument 0 +push constant 0 +lt +if-goto IF_TRUE0 +goto IF_FALSE0 +label IF_TRUE0 +push constant 40 +call String.new 1 +push constant 69 +call String.appendChar 2 +push constant 114 +call String.appendChar 2 +push constant 114 +call String.appendChar 2 +push constant 111 +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 +push constant 115 +call String.appendChar 2 +push constant 113 +call String.appendChar 2 +push constant 117 +call String.appendChar 2 +push constant 97 +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 114 +call String.appendChar 2 +push constant 111 +call String.appendChar 2 +push constant 111 +call String.appendChar 2 +push constant 116 +call String.appendChar 2 +push constant 105 +call String.appendChar 2 +push constant 110 +call String.appendChar 2 +push constant 103 +call String.appendChar 2 +push constant 32 +call String.appendChar 2 +push constant 97 +call String.appendChar 2 +push constant 32 +call String.appendChar 2 +push constant 110 +call String.appendChar 2 +push constant 101 +call String.appendChar 2 +push constant 103 +call String.appendChar 2 +push constant 97 +call String.appendChar 2 +push constant 116 +call String.appendChar 2 +push constant 105 +call String.appendChar 2 +push constant 118 +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 46 +call String.appendChar 2 +call Output.printString 1 +pop temp 0 +push constant 0 +call Sys.error 1 +pop temp 0 +label IF_FALSE0 +push argument 0 +call Math.length 1 +push constant 2 +call Math.divide 2 +pop local 1 +push constant 0 +pop local 0 +label WHILE_EXP0 +push local 1 +push constant 0 +lt +not +not +if-goto WHILE_END0 +push local 0 +push local 1 +push static 0 +add +pop pointer 1 +push that 0 +add +pop local 2 +push local 2 +push local 2 +call Math.multiply 2 +pop local 3 +push local 3 +push argument 0 +gt +not +push local 3 +push constant 0 +gt +and +if-goto IF_TRUE1 +goto IF_FALSE1 +label IF_TRUE1 +push local 2 +pop local 0 +label IF_FALSE1 +push local 1 +push constant 1 +sub +pop local 1 +goto WHILE_EXP0 +label WHILE_END0 +push local 0 +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 +return +goto IF_END0 +label IF_FALSE0 +push argument 1 +return +label IF_END0 +function Math.min 0 +push argument 0 +push argument 1 +lt +if-goto IF_TRUE0 +goto IF_FALSE0 +label IF_TRUE0 +push argument 0 +return +goto IF_END0 +label IF_FALSE0 +push argument 1 +return +label IF_END0 diff --git a/projects/12/MathTest/MathTest.out b/projects/12/MathTest/MathTest.out new file mode 100644 index 0000000..8b5a504 --- /dev/null +++ b/projects/12/MathTest/MathTest.out @@ -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 |  | 
