Can someone explain how this last bit determine ng precisely? I was told ng is 1 if it's negative and o if it's positive or 0. But where does it says that negative is 1? It kind of counter my logic since -1 is less than 0 and since 0 is false (0) then negative should be false. But instead I was told negative is true? Please help me untangle this confused mind! Also, how is otherwise (positive or 0) false if we're directly feeding ng from pin 15?
determining what those values mean is entirely up to the hardware designer.
The designer of the HACK ALU decided that if out is set (1), then that means the entire value of out is a negative value. If that bit is not set (0), then we have a positive value.
But, in this case, it all stems from how to represent a negative number in binary. Because binary numbers have no concept of negative numbers by themselves, so it was decided that if the most significant bit is set, then we have a negative number.
You are confusing a few different topics, so let's see if we can straighten them out a bit.
If we only have 1 bit, then we have two possible states. We can call these 0 and 1, HI and LO, True and False, Fred and Ginger -- pick your poison. The usual convention (not the only one) is to say that 0, LO, and False use the same representation while 1, HI, and True use the other. There's no convention for Fred and Ginger.
If we have a multi-bit value, then when we use that value to represent Boolean values, we need to pick two of the possible values to use. Since we have 16 bits, we have 65,536 possible bit patterns to choose from. The easy one is to say that a pattern of all zeros is False and this is almost universally the one that is chosen. But what about True? There's actually two issues here. One is if I am reading a value and interpreting it as a True or a False. I want EVERY possible pattern to be readable as one or the other. Most languages, C, Java, Jack, etc, use the convention that when you interpret a multibit pattern as a Boolean value, then it is False if and only if it is exactly zero (meaning each and every bit is a 0). Each and every other possible pattern will be treated as a True. But if you are generating a Boolean value as the result of an expression (for instance, a relational expression such as a < b), then you will generate a 0 if the result is False and you will generate a specific pattern if the result is True; in C and Java and many other languages, that specific pattern is a 1 (i.e., every bit is a zero except the lsb), while Jack and BASIC (at least most older versions) and some other languages say that you will generate a -1 (i.e., every bit is a one). There are pros and cons each way. One advantage to using -1 is that if you simply do a bitwise NOT of 0, you get -1 and if you do a bitwise NOT of -1 you get 0. If you do a bitwise NOT of 1, you get -2, which would still be interpreted as a True Boolean value.
As for the ng signal. That signal is defined as being 1 whenever the 16-bit output of the ALU is less than zero (i.e., strictly negative). BECAUSE we are using a two's complement representation for our integers, the msb is a 1 exactly when the number is strictly negative. Had we used a different representation for our integers, such as offset, one's complement, or even signed-magnitude, this wouldn't be case. But we ARE using two's complement, so it IS the case, hence the msb of the ALU output is all we need to look at to determine if the number the output represents (when it is interpreted as a number, which is not always the case) is negative.