why do (FF + (-7) ) and (FF - 7) make different results?

Started by jackheroes, August 15, 2011, 04:05:46 AM

Previous topic - Next topic

jackheroes

mov al, 0FFh
;ADD al, 0F9h   ;255 + (-7)
;SUB al, 7h     ;255 -  7

These two statements use the same adding operation inside cpu. 1111 1111 + 1111 1001,
but their CF flag are different, add( CF = 1 ), sub( CF = 0 ).
I am confused, my book doesn't say anything about ADD and SUB will result different FLAG state, and how does cpu set the flags after SUB operation.
Could I have some opinions?

dedndave

the result in AL will be the same
but, you are starting out with -1, not 255

that is to say, if you want to treat the operation in the context of signed values, then you have to treat all of them as signed

(-1) + (-7) = -8
(-1) - (7) = -8

in signed operations, the carry flag has little signifigance
it is the overflow and sign flags that contain useful information
this is evident from looking at the conditional branch instructions and which flags they "examine"
****************************************************************
Unsigned Branches
----------------------------------------------------------------
Instruction  Description               Condition       Aliases
----------------------------------------------------------------
JA           Jump if above             CF=0 and ZF=0   JNBE
JAE          Jump if above or equal    CF=0            JNC JNB
JB           Jump if below             CF=1            JC JNAE
JBE          Jump if below or equal    CF=1 or ZF=1    JNA
****************************************************************

****************************************************************
Signed Branches
----------------------------------------------------------------
Instruction  Description               Condition       Aliases
----------------------------------------------------------------
JG           Jump if greater           SF=OF or ZF=0   JNLE
JGE          Jump if greater or equal  SF=OF           JNL
JL           Jump if less              SF<>OF          JNGE
JLE          Jump if less or equal     SF<>OF or ZF=1  JNG
JO           Jump if overflow          OF=1
JNO          Jump if no overflow       OF=0
JS           Jump if sign              SF=1
JNS          Jump if no sign           SF=1
****************************************************************


now, if you treat them as unsigned values, then the carry flag has meaning
255 + 249 = 504, which will result in the carry flag being set, and the 8 bits = 248
255 -7 = 248, with the carry flag being cleared

this is called "two's compliment"
it is how you are able to use the same registers to represent either signed or unsigned values
the range for a byte value is.....
0 to 255 unsigned
or
-128 to 127 signed

jackheroes

What you said is how you handle the operation, not the CPU.
I mean in circuit level, how does CPU set CF, CPU doesn't know FF is (-1) or (255) at circuit( bit ) level.My book says when do the adding, the number of result bits is larger than the operand,CF is set to 1(coz an extra 1 is carried into CF). But it doesn't say how cpu handle CF when do the SUB,I know SUB is converted to add, but with this add the rules for setting flags seems different than the direct adding operation.

dedndave

use these rules....

if the result of an addition or subtraction requires more bits than the unsigned limit of the register, carry will be set
otherwise, the carry flag will be cleared

if the result of an addition or subtraction requires more bits than the signed limit of the register, overflow will be set
otherwise, the overflow flag will be cleared

these rules do not apply to some other instructions
for instructions like DIV or MUL, it's best to ignore the flags
that is because they behave a little differently on different CPU's

some instructions are special, like DEC, INC, NOT, and NEG
most logic instructions, like OR, XOR, AND, TEST always clear the carry flag
that is because there is no logical equivalent of a carry condition - bits do not ripple

MichaelW

Quote from: jackheroes on August 15, 2011, 05:00:57 AM
What you said is how you handle the operation, not the CPU. I mean in circuit level...

Programmers work with the CPU in terms of a programming model. To know what is going on at a circuit level you would need to ask the designers of the circuits.

From the IA-32 Intel Architecture Software Developer's Manual, Volume 2A, for the ADD instruction:

"The ADD instruction performs integer addition. It evaluates the result for both signed and unsigned integer operands and sets the OF and CF flags to indicate a carry (overflow) in the signed or unsigned result, respectively. The SF flag indicates the sign of the signed result."

And from Volume 2B, for the SUB instruction:

"The SUB instruction performs integer subtraction. It evaluates the result for both signed and unsigned integer operands and sets the OF and CF flags to indicate an overflow in the signed or unsigned result, respectively. The SF flag indicates the sign of the signed result."


eschew obfuscation