I think I'm getting a much better feeling for where you are going astray.
Jeana wrote
Ok, when I was saying flags I meant the instruction pins. My background includes a lot of shell coding, flags are used for instruction modifiers, so I used the term in the wrong context on accident. I apologize for the confusion.
Each control signal tells the ALU to do a very specific thing -- nx, for instance, tells the ALU to take the bitwise complement of the x input (after first being operated on by the zx signal).
The collection of the six input signals results in an overall relationship between the output and the inputs that defines an instruction. The relationship realized by each instruction can be expressed as an arithmetic relationship between x and y and, in some cases, as a bitwise logical relationship. In all of the arithmetic relationships, the inputs are generally interpreted as two's complement values.
There are therefore 64 instructions, although not all of them are unique. The authors chose 18 of them as the Instruction Set for the Hack.
Let's consider the instruction where zx=nx=zy=0 and ny=f=no=1 and see what the relationship is.
Since zx and nx are both unasserted, the ALU gets the x input directly.
Since zy is unasserted but ny is asserted, the ALU gets !y.
Since f is asserted we add x and !y
Since no is asserted we take the bitwise inverse of the adder's output.
The net result is that we have
!(x + !y)
Now, we know that with 2's complement we have the following relation between the additive inverse of a number and the bitwise complement
-n = !n + 1
That means that
!n = -n-1 = -(n+1)
So leveraging that knowledge, we can write our ALU output for this instruction as
!(x + !y) = !(x + -(y+1)) = !(x - y -1) = -(x - y - 1 + 1) = -(x - y) = y - x
So if we want to compute y-x, we can do so by setting the ALU control signals to these values.
I know that the numbers can be processed as input if they were already in 2s complement (specifically useful if further computations would be completed on that variable). However from the external data entry point of view, a user would (presumably) send a positive numbers with the negate (flags) instructions to produce a product of 2 negative numbers. Maybe this kind of math would require further processing outside the ALU?
Remember that we are talking about assembly language programs at this level. If we want to load -42 into the D register, we do that with a sequence of two instructions.
@42
D = -A
The -A instruction will set zx=nx=f=no=1 and zy=ny=0. It will also set a bit that will route the contents of the A register to the y input of the ALU (as opposed to the value stored in RAM at the address stored in the A register).
The relationship for this set of control signals is therefore
!(!0 + y) = !(!0 + A) = !(-(0+1) + A) = !(A-1) = -(A-1 + 1) = -A
I am aware of using an Xor combined with a half-adder for 2s complement, building a sub-chip for this concept is part of what set off this entire investigation for me. The use of the full adder was the workaround (vice creating a 2s complement chip separate or other integrated methods) I was talking about. Maybe it could be called more of a shortcut then a workaround?
Since carry operations are part of an adder, this can (and does) work under most conditions. I would assume that under extreme high and low numbers this may fail, but haven't tested this.
That method does seems breaks down when both nx, ny instructions are set, at least with the testing I have done so far. Assuming the goal is specifically arithmetic.
It's important to keep in mind that nx and ny are NOT flags or instructions. They are control signals that perform a very simple, specific task. If nx is 1 then the x input to the ALU is bitwise negated otherwise it is passed through unmodified. That's what it does and that is all that it does.
I really do not understand how nx,ny,f=1 (rest=0) are meant to translates to -(x+y+2) aka -x-y-2.
I understand that this is the result, but it wasn't my intended operation?
It's unclear to me what about this you do and what you do not understand. When you configure the control signals that way, you get the following:
!x + !y
To convert this to 2's complement arithmetic terms we have
!x + !y = -(x+1) + -(y+1) = -(x+y+2)
I understand how this condition is created (between the bitwise not and the adder), but the why when using addition this should occur is kind of the issue to me. Shouldn't the ALU account for the difference between bitwise instructions and math operations?
The ALU can't read our minds. It takes two patterns of input bits and produces an output bit pattern according to the effects that its six control signals perform. That's all it does. WE assign meaning to the relationships between those patterns.
I would have thought that those instructions should produce = -x + (-y) = -x-y. Is this were I am misunderstanding the operations?
Why? You are still trying to think of nx as being a flag telling the ALU that it should treat the input at its x input as the additive inverse of that value. That's NOT what nx does; ALL it does is make the ALU do a bitwise negation of the value on the x data path before sending it to both the 16-bit adder and the 16-bit AND gate.
I will have to try the x to -1234, y to -5678 test later. I assume you mean using positive x and y, then using the nx and ny instructions?
In your test file (or in the ALU emulator running in interactive mode) you can force the x and y inputs to be whatever bit pattern you want (the same way that the test file sets one of them to -1 for some of the tests).
-1234 = b1111 1011 0010 1110
-5678 = b1110 1001 1101 0010