News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Calculating Parity

Started by asm_coder, April 27, 2010, 11:12:23 AM

Previous topic - Next topic

asm_coder

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.

dedndave

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)

FORTRANS

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.

dedndave

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

jj2007

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

dioxin

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.

dedndave

#6
they more or less casterated the usefulness of that function, huh   :lol

asm_coder

thanks guys for the examples I get its logic now.

asm_coder.

jj2007

I still don't understand why an inc ah clears the parity flag, while a dec ah following immediately does nothing. Any ideas?

dedndave

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

FORTRANS

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

dioxin

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.

dedndave

Paul got ya, Jochen - er - ah - all of us
i think asm_coder set a trap and most of us fell in   :bdg

dedndave

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

jj2007

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