2017-05-13 2 views
-1

zählen Dies ist Assembly-Code. Es sollte zählen, wie oft es eine Umwandlung von 1 zu 0 oder 0 zu 1 in einem Zeichen ist.wie die Anzahl der 1/0-Bits in char [Assembly]

void main() 
{ 

unsigned char vet[] = { 0x06 }; //Array di byte (da considerare come 
           //una sequenza di bit) 
unsigned short int len = 4;    //Lunghezza (numero di bit) 

             // Output 
unsigned int transizioni01;    //Numero di transizioni 0->1 
unsigned int transizioni10;    
    __asm{XOR EAX, EAX 
     XOR EBX, EBX 
     MOV transizioni10, 0 
     MOV transizioni01, 0 
TORNO: 
     CMP BX, len 
     JA FINE 
     MOV AL, vet[EBX] 
     TEST AL, 1 
     JNZ UNO 

     INC BX 
     MOV AL, vet[EBX] 
     TEST AL, 1 
     JZ ZEROUNO 

UNO: INC BX 
     CMP BX, len 
     JA FINE 
     MOV AL, vet[EBX] 
     TEST AL, 1 
     JNZ TORNO 

UNOZERO:INC transizioni10 
     JMP TORNO 
ZEROUNO:INC transizioni01 
     JMP TORNO 

FINE:} 

Es funktioniert nicht.Kann jemand mir irgendwelche Änderungen vorschlagen?

+0

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

Antwort

0

Ich habe nicht versucht, den Code zu verstehen, aber die folgende Alternative funktioniert:

//Assume EAX = pointer to input array of integer 
//Assume EDX = length of array in bytes 
//Length must be a multiple of 4. 
    push edi    //Save non-volatile registers 
    push ebx    //I.e. everything but eax,ecx,edx 
    xor edi,edi   //change count = 0 
    lea eax,[eax+edx]  //array = end of array 
    neg edx    //length = - length 
    //we turn the counter around, so the loop is more efficient. 
    jz @Done    //if length = 0 -> done 
@OuterLoop: 
    mov ebx,[eax+edx]  //x = array[end - length] => x = array[begin] 
@InnerLoop 
    bsf ecx,ebx  //count leading zero's, cl = LSB zero-count 
    jz @RemainderIsZero 
    inc edi   //If reg is non-zero then at least 1 change. 
    shr ebx,cl  //shift out the bits we've counted 
    not ebx   //Invert the data, force LSB to be zero 
    jmp @InnerLoop //repeat until data = 0 (until no more changes) 
@RemainderIsZero:  
    add edx,4   //see if more data needs to be processed 
    jnz @OuterLoop //remember edx is negative 
@Done: 
    mov eax,edi  //return the count in eax 
    pop ebx   //restore the non-volatile registers. 
    pop edi 
    //ret    //You can only do RET if the compiler does NOT 
        //use stack frames. 
+0

Aber ich muss die Anzahl der Übergänge 1 0 und die Übergänge 0 berechnen 1 in separaten Variablen. wie kann ich? danke für deine Antwort –

0

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.

+0

es ist richtig, aber es gibt ein Problem, das gleiche mit meinem Programm. Wenn Sie len = 1 und vet [] = {0x01} eingeben, lautet die Ausgabe 01 = 1 und 10 = 0, aber die wahre Ausgabe sollte 0 und 0 sein. Warum dieses Problem? –

+0

@marcoteto ?? Eingabe ist 0x01 => 0000 0001 -> ein Übergang von 0 nach 1. Ausgabe sieht für mich korrekt aus. Für die Ausgabe 0/0 geben Sie 'vet [] = {0};' oder 'vet [] = {0xFF};' ein (für 'len = 1;' natürlich) – Ped7g

+0

@marcoteto oh wait .. mein Code dauert 'len 'als Anzahl von BYTES, nicht Bits ... also, das ist das Problem. Für meinen Code sind nur 8 * len Bitlängen möglich. – Ped7g

Verwandte Themen