News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Why don't INC and DEC affect the carry flag?

Started by RedSkeleton007, July 14, 2015, 04:50:26 AM

Previous topic - Next topic

RedSkeleton007

If we were to add 1 to a integer with all bits not set to 0, the carry flag (CF) would activate:

mov ax,0ffffh
add ax,1 ;AX = 0000, CF = 1

Why then would incrementing by 1 NOT produce the same result (since it's the same as adding 1):

mov ax,0ffffh
inc ax

To make things more confusing, the book also says: "The INC and DEC instructions do not affect the carry flag. Applying the NEG instruction to a nonzero operand always sets the carry flag."
I thought the carry flag's responsibility was only supposed to set when a value is too large to fit in its destination operand. If the value is negated, wouldn't the value be TOO SMALL instead?

dedndave

there are times when INC or DEC are used in loops where the carry flag is used for something else
INC/DEC are used on the loop counter - but the carry flag is allowed to "ripple" from one loop pass to the next

if you want to test the result of INC going from 0FFFFh to 0, you can use JZ or JNZ
if you want to test the result of DEC going from 1 to 0, again, you can use JZ or JNZ
if you want to test the result of DEC going from 0 to -1, you can use JS or JNS

dedndave

an example might be....

let's say you have 2 very long integers that are several dwords in length

int1 dd 1,0,0,0,0,0,0,1
int2 dd 1,0,0,0,0,0,0,1


now, you want to add int2 to int1...

        mov     edi,offset int1
        mov     esi,offset int2
        mov     ecx,8                 ;ECX = loop count
        clc                           ;start out with carry flag cleared

loop00: mov     eax,[esi]
        adc     [edi],eax             ;with carry from previous loop pass
        dec     ecx                   ;adjust loop count
        lea     esi,[esi+4]           ;point to next source dword
        lea     edi,[edi+4]           ;point to next destination dword
        jnz     loop00


and, the loop exits with the carry flag for the overall operation

Tedd

Quote from: RedSkeleton007 on July 14, 2015, 04:50:26 AM
If we were to add 1 to a integer with all bits not set to 0, the carry flag (CF) would activate:

mov ax,0ffffh
add ax,1 ;AX = 0000, CF = 1

Why then would incrementing by 1 NOT produce the same result (since it's the same as adding 1):

mov ax,0ffffh
inc ax

In theory, you're correct. In practice, it was purposely designed that way. So the answer is simply "because."
Of course, the designers had some intention behind it, the Intel manual specifically says "[INC] allows a loop counter to be updated without disturbing the CF flag."

Quote
To make things more confusing, the book also says: "The INC and DEC instructions do not affect the carry flag. Applying the NEG instruction to a nonzero operand always sets the carry flag."
I thought the carry flag's responsibility was only supposed to set when a value is too large to fit in its destination operand. If the value is negated, wouldn't the value be TOO SMALL instead?
The purpose of the carry flag is to provide an extra bit to avoid information loss in both addition (carry) and subtraction (borrow).
Negation is effectively a subtraction from zero; zero minus zero is zero (no borrow), zero minus anything else produces a borrow (indicated by the carry flag.)
Potato2

jj2007

Quote from: Tedd on July 15, 2015, 12:34:42 AMThe purpose of the carry flag is to provide an extra bit to avoid information loss in both addition (carry) and subtraction (borrow).
Negation is effectively a subtraction from zero; zero minus zero is zero (no borrow), zero minus anything else produces a borrow (indicated by the carry flag.)

Nicely explained :t

Grincheux

Quote

In 64-bit mode, INC r16 and INC r32 are not encodable (because opcodes 40H through 47H are REX prefixes).
Otherwise, the instruction's 64-bit mode default operation size is 32 bits. Use of the REX.R prefix permits access to
additional registers (R8-R15). Use of the REX.W prefix promotes operation to 64 bits.

Mikl__

#6
Hi, RedSkeleton007!
This legacy left by Intel microprocessors 8008 and 8080.
Schematic symbol for a 1-bit full adder with Cin and Cout drawn on sides of block to emphasize their use in a multi-bit adder

Full-adder logic diagram

4-bit adder with carry lookahead

INC and DEC commands doesn't change the value of carry flag CF, since implemented in other circuitry based

Grincheux


Mikl__

Hi, Grincheux!
That can not be programmed in assembly language, it is necessary to solder
(©  Russian folklore)

TouEnMasm

AMD general instructions book
flag affected by INC
OF,SF,ZF,AF,PF

11 OF Overflow Flag R/W
10 DF Direction Flag R/W
7  SF Sign Flag R/W
6  ZF Zero Flag R/W
4  AF Auxiliary Carry Flag R/W
2  PF Parity Flag R/W
0  CF Carry Flag R/W


Carry Flag (CF).  Bit 0.
Hardware sets the carry flag to 1 if the last integer addition or subtraction operation resulted in a carry (for addition) or a borrow (for subtraction) out of the most-significant bit position of the result. Otherwise, hardware clears the flag to 0.
The increment and decrement instructions—unlike the addition and subtraction instructions—do not affect the carry flag. The bit shift and bit rotate instructions shift bits of operands into the carry flag. Logical instructions like AND, OR, XOR clear the carry flag. Bit-test instructions (BTx) set the value of the carry flag depending on the value of the tested bit of the operand.
Software can set or clear the carry flag with the STC and CLC instructions, respectively. Software can complement the flag with the CMC instruction.

Parity Flag (PF).  Bit 2.
Hardware sets the parity flag to 1 if there is an even number of 1 bits in the least-significant byte of the last result of certain operations. Otherwise (i.e., for an odd number of 1 bits), hardware clears the flag to 0. Software can read the flag to implement parity checking.
Auxiliary Carry Flag (AF).  Bit 4. Hardware sets the auxiliary carry flag to 1 if the last binary-coded decimal (BCD) operation resulted in a carry (for addition) or a borrow (for subtraction) out of bit 3. Otherwise, hardware clears the flag to 0.
The main application of this flag is to support decimal arithmetic operations. Most commonly, this flag is used internally by correction commands for decimal addition (AAA) and subtraction (AAS).

Zero Flag (ZF).  Bit 6.
Hardware sets the zero flag to 1 if the last arithmetic operation resulted in a value of zero. Otherwise (for a non-zero result), hardware clears the flag to 0. The compare and test instructions also affect the zero flag.
The zero flag is typically used to test whether the result of an arithmetic or logical operation is zero, or to test whether two operands are equal.

Sign Flag (SF).  Bit 7.
Hardware sets the sign flag to 1 if the last arithmetic operation resulted in a negative value. Otherwise (for a positive-valued result), hardware clears the flag to 0. Thus, in such operations, the value of the sign flag is set equal to the value of the most-significant bit of the result. Depending on the size of operands, the most-significant bit is bit 7 (for bytes), bit 15 (for words), bit 31 (for doublewords), or bit 63 (for quadwords).

Direction Flag (DF).  Bit 10.
The direction flag determines the order in which strings are processed. Software can set the direction flag to 1 to specify decrementing the data pointer for the next string instruction (LODSx, STOSx, MOVSx, SCASx, CMPSx, OUTSx, or INSx). Clearing the direction flag
36 General-Purpose Programming
AMD64 Technology 24592—Rev. 3.14—September 2007
to 0 specifies incrementing the data pointer. The pointers are stored in the rSI or rDI register. Software can set or clear the flag with the STD and CLD instructions, respectively.

Overflow Flag (OF).  Bit 11.
Hardware sets the overflow flag to 1 to indicate that the most-significant (sign) bit of the result of the last signed integer operation differed from the signs of both source operands. Otherwise, hardware clears the flag to 0. A set overflow flag means that the magnitude of the positive or negative result is too big (overflow) or too small (underflow) to fit its defined data type.
The OF flag is undefined after the DIV instruction and after a shift of more than one bit. Logical instructions clear the overflow flag.
Fa is a musical note to play with CL

Mikl__

Hi, ToutEnMasm!
RedSkeleton007 asked
QuoteWhy don't INC and DEC affect the carry flag?
"AMD general instructions book" confirms INC and DEC don't affect the carry flag, but "AMD general instructions book" doesn't show why not affect the carry flag

TouEnMasm

The instructions of the microprocessor try to cover all the need.
Inc is faster than add but isn't so powerfull.
If you don't need the carry flag,you use "inc" and if you need it you use add.
If you win one µs with "inc" this seem to be not significant,but if the operation is repeated many time
you can win seconds and then minutes.
Fa is a musical note to play with CL

jj2007

Quote from: Mikl__ on December 26, 2015, 12:16:04 PM... doesn't show why not affect the carry flag

See Tedd's answer above:
QuoteIntel manual specifically says "[INC] allows a loop counter to be updated without disturbing the CF flag."

CF has a specific role in addition and subtraction, so inc allows to perform these in a loop.

Quote from: ToutEnMasm on December 26, 2015, 09:41:32 PMInc is faster than add

Never. Speed is identical on most modern CPUs (and Hutch will find examples where add is faster ;))

Gunther

Quote from: jj2007 on December 26, 2015, 10:33:22 PM
Never. Speed is identical on most modern CPUs (and Hutch will find examples where add is faster ;))

That could be. Agner says in the Optimizing subroutines in assembly language. An optimization guide for x86 platforms, p. 141:
Quote
The INC and DEC instructions do not modify the carry flag but they do modify the other arithmetic flags. Writing to only part of the flags register costs an extra μop on P4 and P4E. It can cause a partial flags stalls on some Intel processors if a subsequent instruction reads the carry flag or all the flag bits. On all processors, it can cause a false dependence on the carry flag from a previous instruction. Use ADD and SUB when optimizing for speed. Use INC and DEC when optimizing for size or when no penalty is expected.

Gunther
You have to know the facts before you can distort them.

TouEnMasm

Fa is a musical note to play with CL