Posted by
ivant on
URL: http://nand2tetris-questions-and-answers-forum.52.s1.nabble.com/Problems-understanding-Hardware-Software-interface-tp4032625p4032628.html
cdrh wrote
Another problem, how is the 2s complement system implemented? How does the 16-bit computer know 0000 0000 0000 0001 is ONE? Who's telling it that? It seems like we just built hardware and said "hey here's this system called 2s complement. it's a translation of our decimal system". And the computer just somehow magically recognizes it. Again, same problem here. All we have is an ALU and memory. Who and what is doing this decoding?
You are closer to the truth than you realize! The computer doesn't know anything about two's complement, or for decimal numbers... or for that matter for binary numbers! It just "knows" about 0 (low voltage) and 1 (high voltage) and it has some gates which make it produce specific outputs. For example, we create a gate, which has two inputs and two outputs, with the following truth table:
X Y | C S
0 0 | 0 0
0 1 | 0 1
1 0 | 0 1
1 1 | 1 0
We call it half-adder, because 0 + 0 = 00, 0 + 1 = 01, 1 + 1 = 01 and 1 + 1 = 10. Does this mean that the computer now knows how to add? No. It is us who interpret this as addition. The computer wouldn't care if the last row produced 11 instead. It doesn't know how to add.
But we know how to combine gates like the half adder and full adder and AND, NOT, OR, MUX, etc. to make it act in ways which we want it to. For example we can create a circuit of 1 half-adder and 15 full-adders in such a way, that if we give it two sequences of 16 binary digits, which we interpret as two 16-bit binary numbers, it will produce another sequence of 16 binary digits, which if again interpreted as a 16-bit binary number is exactly the sum of the 2 inputs.
So great! We have a calculator which can add. Now we want to make it subtract as well. One way would be to create a separate circuit for subtraction. It would be more complex, because we need to handle borrows. Also, if the first number is smaller than the second, we'll have a negative result. How do we represent this?
(I'll start using 4 bit numbers because it's too much writing)
With 4 bits we can represent 2^4 = 16 different combinations. We can interpret these as numbers from 0 (0000) to 15 (1111). But we want to be able to represent negative numbers as well. We can use 2's complement representation, which goes like this:
1000 -8
1001 -7
1010 -6
1011 -5
1100 -4
1101 -3
1110 -2
1111 -1
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
So, numbers with their highest bit 1 are negative numbers. To find their opposite number, we need to compute their 2's complement. This is done by inverting all the bits and adding 1 to the result (and ignoring the overflow if there is any). For example the 2's complement of 1011 (-5) is 0100 + 1 = 0101 (which is 5). Two's complement of 0101 (5) is 1010 + 1 = 1011 (-5). What about 0? It's 2's complement is 1111 + 1 = 1|0000, or again 0 because we just ignore the overflow.
Why using this representation? Because it allows us to treat the subtraction as addition. For example instead of computing 5 - 3 we'll compute 5 + (-3).
0101 - 0011 =
0101 + 1101 =
1|0010 which is the representation of 2.
Another example: 3 - 6
0011 - 0110 =
0011 + 1010 =
1101 (-3)
So, if we choose to interpret the binary strings as numbers encoded in 2's complement, we can use the same adder to also implement subtraction. Notice that we only had to add a small circuitry to compute 2's complement.
Hopefully, I managed to clear things up for you. If you have more questions about that just ask and I'll try to answer.