In x86 开发者_如何学JAVAassembly, 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.
Try this:
foo: cmp byte [foo],0x7F
Note: This cmp
instruction's first byte is 0x80, and 0x80-0x7F = 0x01.
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
.
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:
kortest*
,ktest*
(AVX-512)popcnt
(ABM or SSE4.2)ptest
(SSE4.1)rdrand
,rdseed
vtestp*
(AVX)
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.
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.
精彩评论