Lassen Sie uns sagen, dass das Array von Low-Bit nach oben Bit verbindet, dh zwei Bytes 0x0F, 0xF0
wird als Bits behandelt werden streamen 0000 1111 1111 0000
, was zu einer (0 → 1) Änderung und (1 →> 0) Änderung führt. Das erste/letzte Bit ist immer "keine Änderung" (gegen die Lücke daneben), so dass 0xFF, 0xFF
0/0 Übergänge erzeugt und 0x00, 0x00
auch 0/0 Übergänge erzeugt.
Die Idee des Codes ist (X xor (X>>1))
zu verwenden Bitmaske von Bits zu extrahieren, in denen der Übergang („edges“) der Fall ist, dann werden diese zählen Zählwert von „alle“ Übergänge zu erhalten, und als and
mit ursprünglichem Wert X
-ed die Bitmaske von nur "0 → 1" Übergängen wird empfangen und erneut gezählt. Dann muss man am Ende, um die "1-> 0" Übergänge zu zählen, nur "0 -> 1" von "allen" zählen.
; TODO preserve registers which need to be preserved by your ABI
; ax, ebx, ecx, dx, esi, edi will be modified
lea esi,[vet] ; address of byte array
mov ecx,[len] ; number of bytes in array
mov ah,[esi] ; take most significant bit as entry low bit
shr ah,7 ; ah.LSB = [first_byte].MSB (no transition on first bit)
xor ebx,ebx ; counter of ALL transitions
xor edi,edi ; counter of 0->1 transitions
; ## calculate bitmaks of all transitions (marked bit is the second one)
detect_transitions_loop:
mov al,[esi] ; ax = current source byte + low bit of previous in ah
shr ax,1 ; al = 8 bits of array shifted by 1 to right
mov ah,[esi] ; ah = current source byte
inc esi ; ++source byte address
xor al,ah ; al = bitmask of transitions detected
jz no_transition_detected_in_byte
mov dh,al ; dh = copy of all transitions
; ## count all transitions
count_all_transitions:
inc ebx ; increment number of all transitions
; clear least significant set bit of al (removes one transition)
mov dl,al
dec al
and al,dl
jnz count_all_transitions ; until all bits are counted
; ## count 0-1 transitions
and dh,ah ; dh = bits of 0->1 transitions detected
jz no_transition_detected_in_byte
count_01_transitions:
inc edi ; increment number of 0->1 transitions
; clear least significant set bit of dh (removes one transition)
mov dl,dh
dec dh
and dh,dl
jnz count_01_transitions ; until all bits are counted
no_transition_detected_in_byte:
dec ecx
jnz detect_transitions_loop
; ## calculate 1->0 transitions count, and store results
sub ebx,edi
mov [transizioni01],edi
mov [transizioni10],ebx
; TODO restore any registers which had to be preserved
; TODO return
Der Code kann auf einmal 32 Bit zu verarbeiten, verlängert werden (wenn man Pad Eingangsarray Multiplikationen von 4 Eingangsbytes enthalten), und (auf CPUs wo verfügbar) Anweisung popcnt
verwendet werden kann, um die Anzahl der zählen Bits der erkannten Übergänge.
EDIT: eigentlich das Array bei 32bits auf einmal verarbeiten müsste es die Bits in top-> Low und umgekehrte Weise verbunden haben (lesen sie von LSB zu MSB, dh 0x0F = 1111 0000 Strom von Bits), dann loading mov eax,[esi]
würde dies auf Little-Endian-Maschine entsprechen. Es ist also nicht so einfach wie ich dachte.
Um Übergänge herausgefiltert zu bekommen (als Bits, die das zweite Bit des Paares markieren) kann man (x^(x >> 1)) mit dem obersten Bit von sich selbst kopieren, dann für 2nd + char das niedrigste Bit des vorherigen Bytes. Wenn Sie dann dieses Ergebnis mit dem ursprünglichen Wert andieren, erhalten Sie nur 0-> 1 Übergänge, dann können Sie die verbleibenden Bits zählen. Die 1-> 0-Übergänge sind die Anzahl (Ergebnis) -Zählung (0-> 1) ... Ich schreibe dies als rohe Idee aus dem Kopf, ohne es wirklich zu überprüfen, also kann es falsch (vollständig) sein. Es ist auch nicht klar, wie Sie das erste/letzte Bit des bereitgestellten Arrays behandeln und wo sie sich verbinden (niedrig nach oben oder oben zu niedrig?) – Ped7g