5

In x86 assembly, is it possible to clear the Parity Flag in one and only one instruction, working under any initial register configuration?

This is equivalent to creating a result register with an odd number of bits, with any operation that sets flags (expressly excluding mov).

For contrast, setting the parity flag can be done in one instruction:

cmp bl, bl

And there are many ways to clear the parity flag with two instructions:

and bl, 0 
or  bl, 1

However, the one-instruction method remains elusive.

Cody Gray
  • 230,875
  • 49
  • 477
  • 553
  • My guess is no, due to the x86 addressing modes. – Jens Björnhager Jul 16 '10 at 15:23
  • 1
    "mov" doesn't set flags on x86 architecture - only ALU operations do. – Zombie Anchovy Jul 19 '10 at 15:19
  • 1
    The closest I was able to come up with was `or sp, 0xfe`. It only fails to clear PF if the stack pointer was previously at an odd address, which is unlikely because practically all code would keep it aligned. Of course, `or sp, 0xfe` is also practically guaranteed to crash your program in the near future, but the criteria didn't say anything about that :) – Nate Eldredge Apr 20 '22 at 06:34
  • `or bp, 0xfe` won't crash as quickly :) On reasonable platforms, BP is also always aligned. Then again, if the context is that of a general purpose all-assembly program that doesn't care about tooling, all bets are off. – Seva Alekseyev Apr 20 '22 at 18:27
  • @SevaAlekseyev: Well, `bp / ebp / rbp` does get used sometimes as a general scratch register, when it's not needed as a frame pointer; e.g. in a small function that doesn't need a stack frame. `gcc -fomit-frame-pointer` does this regularly, treating it like any other call-preserved register. In this case its value could be anything. But using `sp` as a scratch register would be much more unusual. – Nate Eldredge Apr 21 '22 at 06:49

4 Answers4

5

Try this:

foo:  cmp byte [foo],0x7F

Note: This cmp instruction's first byte is 0x80, and 0x80-0x7F = 0x01.

Brendan
  • 31,872
  • 2
  • 33
  • 57
3

See other answers for tricks like using memory contents, or newer instructions that always clear PF regardless of the bit-pattern in any registers.

Clearing PF is possible in one instruction, but getting an odd number of bits in a result register from the same instruction appears not to be, without known register contents to start with. (mov al, 1 could of course do just the latter part of the question without affecting FLAGS).

The rest of this answer was written considering only the way proposed in the question: using traditional ALU instructions on registers that set PF according to the parity of the low byte of the result.


None of the PF-changing instruction can unconditionally produce an odd-parity result when applied to two copies of a register (like or al, al). Likewise, none of the arithmetic commands produces an odd-parity result when applied to a register and a constant that completely defines the result (like and al, 0 or or al, ffh). As for commands where the second operand is any other constant, the result would depend on the initial value of the register, and we have no control over that.

If we knew some details of the execution environment, it could be possible to use the contents of memory at a well-known address. On PC compatibles in real mode, you can rely on BIOS data structures. In MS-DOS, ditto for executable header. In Windows, there's the TEB as FS:0.

Peter Cordes
  • 286,368
  • 41
  • 520
  • 731
Seva Alekseyev
  • 58,089
  • 23
  • 157
  • 265
  • There was some useful background / basic stuff here in your original answer. With some intro material it's fully salvageable. I edited that into the previous revision, and still think it's worth an upvote for explaining why the approach suggested in the question can't work with one instruction. – Peter Cordes Apr 22 '22 at 03:25
2

If we can go beyond the 8086 itself and into the modern era, more recent x86 instruction sets do contain a number of instructions that unconditionally clear the parity flag, though why they should do so is not always clear. But searching the Intel manuals for PF and looking for strings like "cleared", "set to 0", etc, turns up several:

So ptest xmm0, xmm0 and popcnt eax, eax are probably the most widely available. ptest has the advantage that it doesn't modify any registers other than FLAGS.

The fcomi family is close, as they clear PF when the result of the comparison is any of < > =, but they set it if the result is "unordered", which could happen if x87 registers contain NaN.

(This shows that clearing the parity flag is not equivalent to getting an odd number of bits in an 8-bit register, as there are instructions which will clear it under other conditions.)

I think what these instructions have in common is that they set certain flags (CF, ZF) in specific ways, different from the usual "according to the result". They have no particular need to do anything with the others, but specifying that they remain unchanged would introduce an input dependency on those flags for processors that do not rename them separately. This is a problem for efficient out-of-order execution.

Some instructions handle this issue by specifying that the other flags are "undefined", but for some reason, the designers of these instructions decided to zero them instead.

Nate Eldredge
  • 36,841
  • 4
  • 40
  • 60
1

I think the only way to do it besides mov (I smell interview question) is to find (miraculously, admittedly) a register or register pair that will satisfy TEST src, dst. See here how / when PF is set.

At this moment, no such x86 register/register pair that could satisfy that condition spring to mind.

Michael Foukarakis
  • 38,030
  • 5
  • 79
  • 118
  • Or a memory location that has a well-known value. It was quite possible back in DOS days, when one had a fair chance to encounter and assembly question on an interview. – Seva Alekseyev Jul 16 '10 at 20:42
  • 1
    Re: your dead-link removal edit: https://www.felixcloutier.com/x86/test is a good scrape of Intel's vol.2 PDF. Felix is planning to maintain that domain for the foreseeable future. There's also https://github.com/HJLebbink/asm-dude/wiki/TEST. This answer doesn't really need a link, but for future reference I always link felixcloutier.com when I want to point at some instruction documentation. Also, other single instructions like `inc reg` are possible if you have a zeroed reg and don't mind turning it into a `1`. Non-destructively, there's also `cmp` for different bit-patterns than `test` – Peter Cordes Apr 20 '22 at 22:26
  • Thanks for that, I had hesitated linking to Felix's page for fear it might also go stale. – Michael Foukarakis Apr 21 '22 at 20:20