Question

I'm working on an x86 assembly language homework assignment and do not understand how exactly the test operation effects the carry, zero and sign flags. As I understand it, we are doing a bitwise comparison AND on two operands. In the first example, bits 1,2,3,4, and 7 match up. Does this mean that the result of the AND is 11110010? This would set the sign flag to negative right? Zero flag would not be set because this binary result is not 0. And the carry flag? I'm not really sure how to proceed. Thanks for the help.

mov al,00001111b
test al,00000010b ; a. CF= ZF= SF=<br><br>

mov al,00000110b
cmp al,00000101b  ; b. CF= ZF= SF=<br><br>

mov al,00000101b
cmp al,00000111b  ; c. CF= ZF= SF=<br><br>
Was it helpful?

Solution

As you wrote, x86 TEST operation does a bitwise AND operation. You should check again the truth table for AND:

INPUT   OUTPUT
A   B   A AND B
0   0       0
0   1       0
1   0       0
1   1       1

TEST would do this operation for each 2 corresponding bits in the src and the dst operands, so only bits that are 1 in both would become 1 in the result: 00001111b & 00000010b would simply give 00000010b.

The effect on the flags is now simple to see - ZF=0 since the result is non-zero, SF=0 since the result MSB is off, and CF=0 because TEST won't set it (it's a logical operation, not an arithmetic one).

By the way, TEST is quite cheap as operations go, so you may notice it's used often as a simple zero check - TEST RAX, RAX would AND the RAX register against itself (resulting in the same value of course), so you get a nice way to check if RAX is zero (for e.g. to be used by a je branch immediately after), or negative (by using the SF with a js branch)

Now, the other 2 questions deal with another operation - CMP does an actual subtraction (it's doing the same thing as SUB, but also discards the result, only updating the flags).

  • The first would compute 00000110b - 00000101b = 00000001b, with ZF=SF=0 (for the same reasons as above), and CF=0 since we didn't have any need for carry/borrow.

  • The second would compute 00000101b - 00000111b = 11111110 (two's complement representation for 5 - 7 = -2), ZF is still 0 as above, but this time you'd see SF=1 since we got a negative result so the MSB is on, and CF=1 since the calculation did a "borrow" unto the MSB.

There's a bit of a fine point here regarding CF and its counterpart OF (overflow flag) - the numbers are just numbers, they don't mean signed or unsigned values until you decide to use them as such. However x86 has to maintain the correct flags for any possibility, so it basically uses CF for unsigned operations, effectively meaning that the last operation was 5 - 7 = 254 as if you "borrowed" an extra bit to the MSB (and this is what CF=1 marks here). The OF won't get set because if you consider these exact same operation as signed arithmetic, you've really done 5 - 7 = -2 which is perfectly legal and didn't overflow/underflow.

On the other hand, an operation such as 127 + 127 = 254 would do the opposite, it won't switch the CF (because nothing bad happened if you consider this as unsigned arithmetics), but the OF will get set because if these are signed values, you've just said 127 + 127 = -2 which is obviously wrong because there was an overflow past the max signed value a byte can store (127)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top