5

Here is what I see in the documentation of Intel x86-64 for neg and many other instructions (including sub, so understanding FLAGS for neg x as 0 - x depends on this).

The OF, SF, ZF, AF, and PF flags are set according to the result.

I'm assuming that sf = dest < 0, zf = dest == 0, but can't figure out how the other flags are set.

I see this "set according to the result" phrase everywhere and would appreciate your help in understanding what it means precisely for flags to be set "accordingly".

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
PuzzleAndy
  • 177
  • 1
  • 4
  • 2
    `neg x` implements `0-x`, a completely normal subtraction (`sub`). – Iwillnotexist Idonotexist Nov 08 '16 at 03:28
  • I know from the documentation that dest = -dest for the neg instruction, but I'm wondering how the flags are being modified. In many cases the documentation will define how the flags are set by the instruction in pseudo-code. In some cases it will list a flag as undefined in the "Flags Affected" section. But the "set accordingly" confuses me and I would really like to know what it means. – PuzzleAndy Nov 08 '16 at 03:35
  • 1
    Your answer plus David G's answer resolve my confusion. Thanks for your help! – PuzzleAndy Nov 08 '16 at 04:31
  • I marked this as a duplicate of the newer question, because the real answer to how `neg` sets AF isn't explicit in the accepted answer here. – Peter Cordes Jun 30 '17 at 09:25

1 Answers1

6

So all the of the flags are set based off the operation performed, which is what the phrase "set according to the result" means.

#3.4.3.1 Status Flags The status flags (bits 0, 2, 4, 6, 7, and 11) of the EFLAGS register indicate the results of arithmetic instructions, such as the ADD, SUB, MUL, and DIV instructions. The status flag functions are:

  • CF (bit 0) Carry flag — Set if an arithmetic operation generates a carry or a borrow out of the most- significant bit of the result; cleared otherwise. This flag indicates an overflow condition for unsigned-integer arithmetic. It is also used in multiple-precision arithmetic.
  • PF (bit 2) Parity flag — Set if the least-significant byte of the result contains an even number of 1 bits; cleared otherwise.
  • AF (bit 4) Auxiliary Carry flag — Set if an arithmetic operation generates a carry or a borrow out of bit 3 of the result; cleared otherwise. This flag is used in binary-coded decimal (BCD) arithmetic.
  • ZF (bit 6) Zero flag — Set if the result is zero; cleared otherwise.
  • SF (bit 7) Sign flag — Set equal to the most-significant bit of the result, which is the sign bit of a signed integer. (0 indicates a positive value and 1 indicates a negative value.)
  • OF (bit 11) Overflow flag — Set if the integer result is too large a positive number or too small a negative number (excluding the sign-bit) to fit in the destination operand; cleared otherwise. This flag indicates an overflow condition for signed-integer (two’s complement) arithmetic.

Of these status flags, only the CF flag can be modified directly, using the STC, CLC, and CMC instructions. Also the bit instructions (BT, BTS, BTR, and BTC) copy a specified bit into the CF flag.

Only the CF flag can be modified directly. The others are set based on the operations.

Source - Intel

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
David G
  • 183
  • 7
  • Thanks for referring to the documentation! So are the CF, PF, AF, and OF flags all relying on an addition/subtraction circuit to modify the flags? Is neg using this addition/subtraction circuit, with 0 and dest as operands, in order to modify the flags? I understand digital logic circuits so feel free to get verbose in your answer. – PuzzleAndy Nov 08 '16 at 04:05
  • 4
    Found it. I overlooked it in the "Description" for neg in the documentation. Here's what that says, in case someone stumbles across this question in the future. "Replaces the value of operand (the destination operand) with its two's complement. (This operation is equivalent to subtracting the operand from 0.)" – PuzzleAndy Nov 08 '16 at 04:29
  • 2
    The only thing I know for certain is the flags are set by the CPU after the operation is performed. In the case of NEG per section 7.3.2.4 - _The NEG (negate) instruction subtracts a signed integer operand from zero._ The same section talks about CMP and the flags it updates. What I can't tell you is if it is a specific adder or part of the ALU as that goes to a hardware level that is out of my depth. – David G Nov 08 '16 at 04:38
  • 1
    Just note that you can modify completely the contents in the eflags register with the `popf/popfd/popfq` instructions, except for the `IF` Interrupt Enable, I belive. – wallek876 Nov 08 '16 at 08:10
  • 1
    All flags can be modified directly with the `popf` and `lahf` instructions. – fuz Nov 08 '16 at 12:54
  • 3
    It is true that `POPF` and `SAHF` (not `LAHF`!), as well as others, can modify flags (for instance, `SAHF` writes to `CF`,`PF`,`AF`,`ZF`,`SF` but not `OF`). There are other flags in the `*FLAGS` register that may or may not be able to be modified depending on a number of factors but it is beyond the scope of this question. (It is more complicated than just dealing with `IF` though -- see the documentation for `POPF` for details) – user1354557 Nov 08 '16 at 15:26
  • Really good information guys. I'm still learning all the instructions but I'm glad to know you can modify the flags like that. – PuzzleAndy Nov 08 '16 at 15:58
  • 1
    Seems like the bullet point for PF got lost. For it, the "according to the result" case is even-parity of the low 8 bits of the result, even if the operand-size is wider. (So `horizontal_xor(result & 0xFF) == 0`) – Peter Cordes Feb 03 '21 at 08:44