Comparison and Condition Codes
Condition Code or Status Register (SREG)
We have introduced the idea of a "compare" machine instruction and then a "conditional branch" instruction that depends on the result that was produced by the compare instruction. But where is that result saved? It is in the status register (SREG).
The SREG is an 8-bit register. But it is not treated as an 8-bit value.
Each bit is a true/false flag for some condition that you (the programmer) might have to test for.
These conditions are set by a wide variety of operations. The compare sets some of them, arithmetic operations set some, etc.
The bit flags are 1 if the condition is true, or occurred, and are 0 if it is not true.
The bits and flags are:
- Bit 0: the C flag (Carry): A carry bit to/from the most significant bit occurred. For 2's Complement numbers (2C), this is not meaningful. For unsigned numbers, it means the result was too big.
- Bit 1: the Z flag (Zero): The result was exactly zero. NOTE: the Z bit is 1 when "zero" is true!
- Bit 2: the N flag (Negative): For 2C numbers, the result was negative. For unsigned, this flag is meaningless.
- Bit 3: the V flag (Overflow): a 2C result was too big. Analagous to the C flag, but for signed numbers.
- Bit 4: the S flag (Signed): a precomputed result of (N XOR V). Used by signed conditional branches.
- Bit 5: the H flag (Half Carry): A carry occurred from bit 3 to bit 4 (i.e., half the byte). This is useful only when dealing with BCD numbers, something we do not discuss in this course.
- Bit 6: the T flag (Bit Store): A temporary storage place for one bit.
- Bit 4: the I flag (Interrupt): Set to 1 to enable (allow) interrupts to happen. We will talk about interrupts later.
We will mostly use the first five flags. They are the flags signalling results of normal arithmetic and comparison operations.
Examples:
Calculating the arithmetic condition flags
In this course you will need to be able to calculate the N, V, C, Z and S condition flags by hand from an arithmetic operation.
Z is the easiest. If the result is 0 (i.e., all 0 bits), then Z=1. Notice that Z is 1 when the result is zero, and Z is 0 when the result is not zero. This is because the Z flag is true when the result is zero, and truth is represented by 1.
N is also very easy. It is simply a copy of the uppermost bit of the result. In a byte this is bit number 7 (we count from 0).
C is pretty easy. It represents an unsigned arithmetic overflow or underflow. When the arithetic operation is an addition, C is 1 if there was a non-zero carry out past the uppermost bits of the operands. Thus, in 8-bit addition, if there was a carry of 1 into the 9th bit, then C=1. For a subtract operation, C is 1 if you had to borrow in from a ficticious 9th bit. That is, if to complete the subtraction you needed to borrow in, then C=1, otherwise C=0.
V is analgous to C except for signed numbers. It represents a signed (2C) overflow or underflow. Unlike C, it is not directly tied to a carry out or borrow in -- you can have a carry out in 2C arithmetic and still end up with a valid result! The rule I teach is this: if the signs don't make sense, V=1, otherwise V=0.
In other words, do the operation you need to, then look at the signs of the operands and the result, and ask yourself it they are theoretically possible. For example, if you add two positive numbers, it should be impossible to get a negative result. If you did, then you just had a 2C overflow, and V=1. Here's all the rules in a table, but remember, you can always re-create them by just asking "do the signs make sense?"
Sign OP Sign -> Result Sign V bit P + P -> P 0 P + P -> N 1 P + N -> any 0 N + N -> P 1 N + N -> N 0 P - P -> any 0 N - N -> any 0 P - N -> P 0 P - N -> N 1 N - P -> N 0 N - P -> P 1
The "official" calculation performed by the CPU to calculate the V bit is: if the last two carries are the same, V=0. If they are different, V=1. Recall that we number bits from the right starting at 0, so the most significant bit in a byte, the eighth bit, is termed bit 7. So if the carry from bit 6 to bit 7 and the carry from bit 7 out are different, then V=1; otherwise they are the same and V=0.
Finally the S bit is simply the XOR (Exclusive OR) of the N and V bits that you computed. XOR can be seen as a "difference" operator, so S=1 if N and V are different, otherwise S=0.