The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: asm_coder on April 27, 2010, 11:12:23 AM

Title: Calculating Parity
Post by: asm_coder on April 27, 2010, 11:12:23 AM
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.
Title: Re: Calculating Parity
Post by: dedndave on April 27, 2010, 11:16:23 AM
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)
Title: Re: Calculating Parity
Post by: FORTRANS on April 27, 2010, 11:30:42 AM
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.
Title: Re: Calculating Parity
Post by: dedndave on April 27, 2010, 11:42:05 AM
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
Title: Re: Calculating Parity
Post by: jj2007 on April 27, 2010, 12:24:20 PM
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
Title: Re: Calculating Parity
Post by: 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.
Title: Re: Calculating Parity
Post by: dedndave on April 27, 2010, 12:47:19 PM
they more or less casterated the usefulness of that function, huh   :lol
Title: Re: Calculating Parity
Post by: asm_coder on April 27, 2010, 01:15:38 PM
thanks guys for the examples I get its logic now.

asm_coder.
Title: Re: Calculating Parity
Post by: jj2007 on April 27, 2010, 01:40:08 PM
I still don't understand why an inc ah clears the parity flag, while a dec ah following immediately does nothing. Any ideas?
Title: Re: Calculating Parity
Post by: dedndave on April 27, 2010, 01:51:03 PM
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
Title: Re: Calculating Parity
Post by: FORTRANS on April 27, 2010, 02:58:33 PM
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
Title: Re: Calculating Parity
Post by: dioxin on April 27, 2010, 02:58:54 PM
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.
Title: Re: Calculating Parity
Post by: dedndave on April 27, 2010, 03:06:26 PM
Paul got ya, Jochen - er - ah - all of us
i think asm_coder set a trap and most of us fell in   :bdg
Title: Re: Calculating Parity
Post by: dedndave on April 27, 2010, 03:29:31 PM
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
Title: Re: Calculating Parity
Post by: jj2007 on April 27, 2010, 03:39:42 PM
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
Title: Re: Calculating Parity
Post by: donkey on April 27, 2010, 03:41:31 PM
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
Title: Re: Calculating Parity
Post by: dedndave on April 27, 2010, 03:50:26 PM
i thought about that one Edgar - well - something similar   :P
i don't think it works
Title: Re: Calculating Parity
Post by: donkey on April 27, 2010, 03:56:15 PM
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...
Title: Re: Calculating Parity
Post by: dedndave on April 27, 2010, 03:59:21 PM
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
Title: Re: Calculating Parity
Post by: donkey on April 27, 2010, 04:07:25 PM
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
Title: Re: Calculating Parity
Post by: dedndave on April 27, 2010, 04:10:17 PM
ok - let me see where i went wrong   :lol
Title: Re: Calculating Parity
Post by: asm_coder on April 27, 2010, 04:15:32 PM
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. ?
Title: Re: Calculating Parity
Post by: 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
Title: Re: Calculating Parity
Post by: donkey on April 27, 2010, 04:25:49 PM
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.
Title: Re: Calculating Parity
Post by: asm_coder on April 27, 2010, 04:30:44 PM
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.
Title: Re: Calculating Parity
Post by: clive on April 27, 2010, 04:31:43 PM
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:
Title: Re: Calculating Parity
Post by: 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
Title: Re: Calculating Parity
Post by: asm_coder on April 27, 2010, 04:44:16 PM
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 .....
Title: Re: Calculating Parity
Post by: asm_coder on April 27, 2010, 04:57:20 PM
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.
Title: Re: Calculating Parity
Post by: dedndave on April 27, 2010, 05:00:51 PM
i am sure..... now   :lol
Title: Re: Calculating Parity
Post by: jj2007 on April 27, 2010, 05:25:14 PM
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
Title: Re: Calculating Parity
Post by: dedndave on April 27, 2010, 05:40:05 PM
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
Title: Re: Calculating Parity
Post by: jj2007 on April 27, 2010, 08:46:50 PM
Quote from: dedndave on April 27, 2010, 05:40:05 PM
why not preserve EAX ?

Great :U