Hi,
I m reading some book about assembly but there is a exercise that I don't quite get
about calculating the parity.
Exercise :
One way to calculate the parity of a 32-bit number in EAX is to use a loop that shifts each bit into Carry flag and accumulates a count of number of times the Carry flag was set ?
I don't really get the logic behind this,since it would be sometimes for example number 9 it would and as we incrementing EDX for example it would be 2
(which isn't an odd parity) :-
I made a code to prove my Point that it wouldn't make odd parity sometimes,incase of odd number and I was right :
.386
.model flat,stdcall
;Challenge : One way to calculate the parity of a 32 - bit number in EAX is to use a loop that shift each bit into the carry flag and accumulates a count of the number of times
;the Carry flag was set. Write a code that does this,and set the Parity flag accordingly, that's quite easy if you understand assembly quite enough to be able to do it the right way.
.code
main proc
mov eax,9;
mov esi,0;
mov ecx,32;
L1:
rcr eax,1;
jnc _IncrementLoop;
inc esi;
_IncrementLoop:
loop L1;
Ret
main endp
END main
maybe there is something I don't quite see here,and someone maybe could clarify it for me.
also there something I don't get,see for example 9 = 1001 which has in lower byte an even parity, -
but when you xor it with itself it would make the parity flag set...
thanks.
asm_coder.
it is much easier than using the carry flag :bg
even parity means that an even number of bits are set
odd parity means that an odd number of bits are set
you can use OR EAX,EAX to set the parity flag according to the value in EAX
you can use PUSHFD/POPFD or LAHF to acquire the parity flag
or, you can use JPO (same as JP) or JPE (same as JNP) to branch conditionally on parity
if you XOR a register against itself, the result is always 0 (even parity)
Hi,
I thought the parity flag only used the low byte?
AX=8080 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0C38 ES=0C38 SS=0C38 CS=0C38 IP=010D NV UP EI PL NZ NA PO NC
0C38:010D 09C0 OR AX,AX
-t
AX=8080 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0C38 ES=0C38 SS=0C38 CS=0C38 IP=010F NV UP EI NG NZ NA PO NC
XOR EDX,EDX
MOV ECX,32
L100:
SHR EAX,1
ADC EDX,0 ; Accumulate bit count.
LOOP L100
TEST EAX,1 ; See if odd parity.
Regards,
Steve N.
i didn't know that, Steve :eek
i have never had a need to use parity - never written low-level modem drivers or anything
however, it doesn't seem logical
if i wanted the parity for AL....
OR AL,AL
the function would seem much more useful if it worked on the full operand size
Here is a snippet for testing in Olly. The inc ah/dec ah sequence is interesting, its behaviour is somewhat unexpected...
include \masm32\include\masm32rt.inc
.code
start:
mov eax, 123456788
inc eax
dec eax
add eax, 1
sub eax, 1
add al, 1
sub al, 1
inc ah ; clears PF
dec ah ; does NOT set PF
add al, 1
sub al, 1
add ah, 1 ; clears PF
sub ah, 1 ; does NOT set PF
exit
end start
Asm_coder,
from the intel manual:
QuotePF (bit 2) Parity flag. Set if the least-significant byte of the result contains an even number of 1 bits; cleared otherwise.
That should explain the parity flag getting set when you xor something with itself. The CPU parity flag indicates that the low byte has even parity.
To calculate parity yourself you can use something like this:
!mov eax,9 'number to find the parity of
!mov ecx,32 'number of bits to do, may be 8 if you have bytes
!mov edx,0 'place where we'll count the bits
lp:
!shr eax,1 'move least significant bit into carry flag
!adc edx,0 'add the carry to the total so far
!dec ecx 'all done?
!jne lp 'no, go back for the next bit
'at this point edx contains a count of the ones in the original number.
'if the LSB of edx is 0 then the original number had even parity, if LSB=1 then it had odd parity
'you could test it by shifting that lsb into the carry flag:
!shr edx,1 'move lsb into carry.
!jc OddParity 'Data has odd parity
!jnc EvenParity 'Data has even parity
Note that "parity" on it's own doesn't mean a lot. You need to be looking for "even parity" when there are an even number of ones or "odd parity" where there is an odd number of ones.
Usually parity bits are used in addition to the number to force odd or even parity to allow for a very basic check of data integrity.
So, where you require odd parity:
Original data data parity parity bit Final data inc parity
needed to force
overall parity
to odd
9 (00001001) Even 1 00001001 1 (3 set bits, odd parity)
27 (00011011) Even 1 00011011 1 (5 set bits, odd parity)
31 (00011111) Odd 0 00011111 0 (5 set bits, odd parity)
Paul.
they more or less casterated the usefulness of that function, huh :lol
thanks guys for the examples I get its logic now.
asm_coder.
I still don't understand why an inc ah clears the parity flag, while a dec ah following immediately does nothing. Any ideas?
not sure i would call it an "idea" Jochen
but - the logical operations affect the flags differently than the math operations
for example, XOR, OR, AND always clear carry
parity should fall in the logical catagory - not that that explains its' odd behaviour
the fact that the parity flag is set on the condition of the low byte only tells me
it was specifically designed for communications - like modem code
as i said, i have not used parity much (if ever - lol)
but, it may have had other usable functions if they had left it's genitals intact
at least i am forewarned
now, i will toss it in the group with AAA, AAD and the other "useful" string math instructions :P
Hi,
Quotethe function would seem much more useful if it worked on the full operand size
Quite. Makes one wonder about the 8086 designers.
QuoteHere is a snippet for testing in Olly. The inc ah/dec ah sequence is interesting, its behaviour is somewhat unexpected...
QuoteI still don't understand why an inc ah clears the parity flag, while a dec ah following immediately does nothing. Any ideas?
True, odd behavior. In DEBUG, it seems that parity is set to
"default" PO for AH and to parity for AL. Seems dumb no matter
how you slice it.
Cheers,
Steve N.
P.S. Oops AH does seem to work, pilot error.
SRN
jj2007,
the behaviour seen is as expected.
Parity is set according to the low byte of the result of the last operation.
Incrementing a number doesn't necessarily change the parity. e.g. 1 and 2 both have odd parity.
When you first inc ah, the parity flag becomes set because the result has even parity. It was clear before the increment because of the previous operation on al (not the previous content of ah).
inc ah ; clears PF ## ah goes from CD to CE (11001110) which has odd parity so the parity bit clears
dec ah ; does NOT set PF ## ah goes from CE to CD (11001101) which also has odd parity so the parity bit correctly stays cleared.
Paul.
Paul got ya, Jochen - er - ah - all of us
i think asm_coder set a trap and most of us fell in :bdg
ok - another shot at this....
should be faster than a loop, if LAHF and SAHF aren't dogs (especially SAHF)
;input in EAX
push eax
or ah,ah
lahf
or al,al
mov al,ah
lahf
xor ah,al
bswap eax
or ah,ah
lahf
or al,al
mov al,ah
lahf
xor ah,al
shr eax,8
xor ah,al
sahf
pop eax
;the parity flag reflects parity of EAX
;all registers are preserved
Quote from: dioxin on April 27, 2010, 02:58:54 PM
Parity is set according to the low byte of the result of the last operation.
Paul,
You hit the nail. Watch what happens with the snippet below...
The point is the interpretation of "low byte of the result". Some of us thought that means al, since al is the low byte of eax. Wrong...!
ah has a low byte, too: ah itself.
include \masm32\include\masm32rt.inc
.code
start:
mov eax, 123456788
inc eax
dec eax
add eax, 1
sub eax, 1
add al, 1
sub al, 1
inc ah ; clears PF
inc ah ; sets PF
inc ah ; clears PF
inc ah ; sets PF
add eax, 65536
add eax, 65536
add eax, 65536
add eax, 65536
add eax, 65536
dec ah ; does NOT set PF
add al, 1
sub al, 1
add ah, 1 ; clears PF
sub ah, 1 ; does NOT set PF
exit
end start
Check eax for parity 32 bits
mov ebx,eax
shr eax,16
xor eax,ebx
xor al,ah
PF is set on even parity
Edgar
i thought about that one Edgar - well - something similar :P
i don't think it works
Hi Dave,
I edited and replaced the popcount method because it was slow and replaced it with a fast one. A check from 0-256 shows the one above is fine:
Line 151: EFLAGS = PF ZF IF 0000
Line 151: EFLAGS = IF 0001
Line 151: EFLAGS = IF 0010
Line 151: EFLAGS = PF IF 0011
Line 151: EFLAGS = IF 0100
Line 151: EFLAGS = PF IF 0101
Line 151: EFLAGS = PF IF 0110
Line 151: EFLAGS = IF 0111
Line 151: EFLAGS = IF 1000
Line 151: EFLAGS = PF IF 1001
etc...
ok
try these values
101h
201h
10001h
20001h
all are even parity
0 to 256 isn't much of a test
for those values, OR EAX,EAX almost works
101h = 100000001 = EFLAGS = PF ZF IF >> correct
201h = 1000000001 = EFLAGS = PF IF >> correct
10001h = 10000000000000001 = EFLAGS = PF ZF IF >> correct
20001h = 100000000000000001 = EFLAGS = PF IF >> correct
ok - let me see where i went wrong :lol
Quote from: dioxin on April 27, 2010, 12:29:18 PM
Asm_coder,
from the intel manual:
QuotePF (bit 2) Parity flag. Set if the least-significant byte of the result contains an even number of 1 bits; cleared otherwise.
That should explain the parity flag getting set when you xor something with itself. The CPU parity flag indicates that the low byte has even parity.
To calculate parity yourself you can use something like this:
!mov eax,9 'number to find the parity of
!mov ecx,32 'number of bits to do, may be 8 if you have bytes
!mov edx,0 'place where we'll count the bits
lp:
!shr eax,1 'move least significant bit into carry flag
!adc edx,0 'add the carry to the total so far
!dec ecx 'all done?
!jne lp 'no, go back for the next bit
'at this point edx contains a count of the ones in the original number.
'if the LSB of edx is 0 then the original number had even parity, if LSB=1 then it had odd parity
'you could test it by shifting that lsb into the carry flag:
!shr edx,1 'move lsb into carry.
!jc OddParity 'Data has odd parity
!jnc EvenParity 'Data has even parity
Note that "parity" on it's own doesn't mean a lot. You need to be looking for "even parity" when there are an even number of ones or "odd parity" where there is an odd number of ones.
Usually parity bits are used in addition to the number to force odd or even parity to allow for a very basic check of data integrity.
So, where you require odd parity:
Original data data parity parity bit Final data inc parity
needed to force
overall parity
to odd
9 (00001001) Even 1 00001001 1 (3 set bits, odd parity)
27 (00011011) Even 1 00011011 1 (5 set bits, odd parity)
31 (00011111) Odd 0 00011111 0 (5 set bits, odd parity)
Paul.
Okay here something I don't get again after thinking more about it,what do you mean by parity needed to force overall parity to odd,for example
we see here that 9 has even bit numbered in it's low byte and when I did loaded in olly I didn't see any instruction that would force an extra bit for example
let's see here this code as in example
mov al,9;
xor al,0;
how did the extra bit get forced then,if there isn't any tests or anything. ?
if you toggle any odd number of bits, parity should reverse
xor al,1
xor al,2
xor al,4
xor al,8
xor al,7
all of those instructions reverse the parity of AL
Hi Dave,
My tests seem pretty reliable, I am using the following setup to test:
START:
mov ecx,StartNumber
TestParity:
mov eax,ecx
// parity check code
mov ebx,eax
shr eax,16
xor eax,ebx
xor al,ah
jnp >
invoke dw2bin,ecx,offset szTestParity ; szTestParity is a 256 byte buffer
PrintString(szTestParity)
:
inc ecx
cmp ecx,StartNumber+256
jl TestParity
invoke ExitProcess, 0
dw2bin FRAME dwValue,lpBuffer
uses edi,eax,ecx,edx
mov edi,[lpBuffer]
mov eax,[dwValue]
mov B[edi+32],0
mov ecx,31
L1:
ror eax,1
setc dl
or dl,30h
mov [edi+ecx],dl
dec ecx
jns L1
RET
ENDF
Every test I do turns out fine.
Quote from: dedndave on April 27, 2010, 04:21:19 PM
if you toggle any odd number of bits, parity should reverse
xor al,1
xor al,2
xor al,4
xor al,8
xor al,7
all of those instructions reverse the parity of AL
I m sorry I typed 9 wrong,what I meant was for example
9 = 1001
which has even set of bits in it's low byte
so when you
mov al,9;
xor al,0;
Parity flag = 1;
even though its even numbered bits.
Both these are workable
; Input in EAX, Output EAX = 1 Odd, EAX = 0 Even
mov edx,eax
shr edx,16
xor eax,edx
mov edx,eax
shr edx,8
xor eax,edx
mov eax,1 ; If you need a flag in EAX
jpo ParityOdd
xor eax,eax ; If you need a flag in EAX
ParityEven:
..
ParityOdd:
; Input in EAX, Output EAX = 1 Odd, EAX = 0 Even
mov edx,eax
shr edx,16
xor eax,edx
mov edx,eax
shr edx,8
xor eax,edx
mov edx,eax
shr edx,4
xor eax,edx
mov edx,eax
shr edx,2
xor eax,edx
mov edx,eax
shr edx,1
xor eax,edx
and eax,1
jnz ParityOdd
ParityEven:
Edgar has the right stuff :U
i ran through all 4,294,967,296 values and compared Edgars against mine
result:
other than the fact that mine has inverted the sense of parity, they match on all values :lol
that is so because i used an odd number of XOR's to derive parity - oops
Edgars is easily smaller and faster than mine
Edgars code wins:
mov ebx,eax
shr eax,16
xor eax,ebx
xor al,ah
never mind I though it's the other way around,in which if odd number of bit,it would set the parity flag,but it was the other way around.
Which make me even wonder it said that parity flag see if number is even or odd,but here 7 = 111 which when you
mov al,7;
xor al,0
that would produce parity of 0,because 7 got odd number of bits which makes me wonder why did they design it like that .....
Quote from: dedndave on April 27, 2010, 04:42:33 PM
Edgar has the right stuff :U
i ran through all 4,294,967,296 values and compared Edgars against mine
result:
other than the fact that mine has inverted the sense of parity, they match on all values :lol
that is so because i used an odd number of XOR's to derive parity - oops
Edgars is easily smaller and faster than mine
Edgars code wins:
mov ebx,eax
shr eax,16
xor eax,ebx
xor al,ah
are you sure that would work ?
because here it would shift al,ah 16 bytes,which would be left is the upper half in which he xor them together to union the numbers,but you would need to union all the numbers
the bytes inside the register to see if it got even or odd number of bits.
i am sure..... now :lol
The Macro :green
include \masm32\include\masm32rt.inc
Parity MACRO arg
ifdifi <eax>, <arg>
mov eax, arg
endif
push eax
shr eax, 16
xor eax, [esp]
add esp, 4
xor al,ah
EXITM <Parity?>
ENDM
.data?
binbuffer db 36 dup(?)
.code
start:
xor ebx, ebx
.Repeat
invoke dw2bin_ex, ebx, offset binbuffer
print offset binbuffer+16 ; lowword only
.if Parity(ebx)
print " has parity", 13, 10
.else
print " has no parity", 13, 10
.endif
inc ebx
.Until ebx>400
exit
end start
why not preserve EAX ?
Parity MACRO arg
ifdifi <eax>, <arg>
mov eax, arg
endif
push eax
shr eax, 16
xor eax, [esp]
xor al,ah
pop eax
EXITM <Parity?>
ENDM