Wie rechnet man am Effizientesten die Parity eines Bytes ? Das Ziel ist
zu wissen ob die Anzahl gesetzter Bits gerade oder ungerade ist. Leider
kann der AVR das nicht in Hardware. Eine For Schleife mit compare leider
ist zuviel Aufwand.
Mir ist da grad ne lustige Lösung in asm eingefallen, frisst allerdings
etwa 600 bytes:
Etwa so:
clr r17
;(parity byte mit 2 multiplizieren, wegen 2byte langem opcode)
lsl r16 ;low byte vo zu bestimmenden parity byte
rol r17 ;carry U.u in r17 reinrollen;
ldi r30 low(IP_vor_ijmp)
ldi r31 high(IP_vor_ijmp)
add r30,r16
adc r31,r17
IP_vor_ijmp:
ijmp
rjmp even parity;(0 hat gerade parität)
rjmp odd parity;(1 hat ungerade parität)
rjmp even parity;(2 hat gerade parität)
rjmp odd parity;(3 hat ungerade parität)
.
.
.
.
rjmp odd parity;(255 hat ungerade parität)
rjmp even parity;(256 hat gerade parität)
odd parity:
....
even parity:
......
11 CPU Cycles, who's faster, C is es sicher nicht :)
Patrick wrote:
> Mir ist da grad ne lustige Lösung in asm eingefallen, frisst allerdings> etwa 600 bytes:> ...> 11 CPU Cycles, who's faster, C is es sicher nicht :)
Du irrst, in C dauerts nur 10 Zyklen und braucht auch nur 20 Bytes.
Ist nämlich ein Assemblermacro in der "parity.h".
Peter
Auf so ein Makro muss man erst mal kommen. Falls jemand Schwierigkeiten
hat, den Assembler-Code nachzuvollziehen:
Seien a bis h die Bits des untersuchenden Werts. a ist das MSB (oberstes
Bit, Bit 7), h das LSB (unterstes Bit, Bit 0). R24 ist also zu Anfang
abcdefgh.
Durch SWAP, EOR(=XOR), 2xLSR, EOR stehen schließlich in den untersten
beiden Bits von R24 (die restlichen sind nicht relevant, "x"):
Bit 1: a XOR c XOR e XOR g = Parity von aceg
Bit 0: b XOR d XOR f XOR h = Parity von bdfh
Damit die Parity des Bytes gerade ist, müssen die Teil-Parities entweder
beide gerade oder beide ungerade sein, d.h.
R24 = xxxxxx00 oder R24 = xxxxxx11.
Nach Addition von 1 (SUBI), gilt dann also
R24 = xxxxxx01 oder R24 = xxxxxx00. Durch ein weiteres LSR und die
Maskierung mit AND wird selektiv das Bit 1 ausgewertet, was im Falle
einer geraden Parity 0 ist und im Falle einer ungeraden Parity 1.
>8 Bit hat ein Byte
Dachte immer, ein Byte hat 8 Bit ;-)
>wir teilen in 2 Hälfen und [...]
Jepp, das ist das Prinzip. In diesem Code kann man es besser erkennen:
1
mov t, a ; a = Input der Routine
2
lsr a
3
lsr a
4
lsr a
5
lsr a
6
eor a, t
7
8
mov t, a
9
lsr a
10
lsr a
11
eor a, t
12
13
mov t, a
14
lsr a
15
eor a, t
16
17
andi a, 1 ; Ergebnis: a = 0[1] wenn Parität even[odd]
Zuerst wird um 8/2 = 4 Stellen rechtsgeschoben, danach um 2 Stellen, und
am Schluss um eine. Dann enthält Bit 0 von a das Ergebnis.
Den "lsr"-Viererblock kann man durch ein "swap a" ersetzen, außerdem
(wie man sich leicht klarmachen kann) die letzten vier Instruktionen
durch diese drei:
1
inc a
2
lsr a
3
andi a, 1
Tut man dies, hat man genau Dirks Code reproduziert.