How does the NEG instruction affect the flags on x

2020-02-01 08:06发布

问题:

The Intel Software Development Manual says this about the neg instruction:

The CF flag set to 0 if the source operand is 0; otherwise it is set to 1. The OF, SF, ZF, AF, and PF flags are set according to the result.

I thought that AF and CF would be set as if neg %eax were replaced by,

not %eax   # bitwise negation
add $1, %eax

But that's not the case, negating 0x6ffffef5 on a real CPU sets AF and CF.

回答1:

neg sets all flags identically to what you'd get with a sub from 0.

This sequence of instructions sets all flags (including AF and CF) identically to neg %eax:

xor  %ecx, %ecx
sub  %eax, %ecx     # ecx = 0 - eax

Intel's documentation does actually specify this, but not in the pseudo-code Operation section or in the flags-affected section of the instruction-set reference (Volume 2) entry for neg itself.

The text of the Description section for neg includes this nugget:

This operation is equivalent to subtracting the operand from 0.

And in Volume 1:

7.3.2.4 Comparison and Sign Change Instructions

[a paragraph about CMP]

The NEG (negate) instruction subtracts a signed integer operand from zero.

The existence of this documentation was pointed out by a comment on an earlier duplicate of this question which isn't as directly worded.

I didn't know that vol.1 had a whole section explaining the instructions. It turns out that not everything Intel has to say about individual instructions is in the Volume 2 insn set reference.


There's some evidence that neg decodes internally to the same uop as a sub instruction on Intel CPUs. (e.g. neg [mem] can micro-fuse the load with the ALU op, as well as micro-fusing the store-address and store-data uops. inc [mem] can only micro-fuse the store, so it's 3 total fused-domain uops).