PDA

View Full Version : [assembly]contare gli 0 in un numero binario


Dr.Speed
08-06-2007, 23:19
devo fare un esercizio in assembly, solo che non ho la piu pallida idea di come, il testo dice: " data una word contare il numero di bit a "0""

credo si usi lo shift per spostare il binario, ma non saprei come:help:

Furla
09-06-2007, 00:53
devi usare una maschera e giocare con lo shift. scegli tu se shiftare la maschera o la word data.

Dr.Speed
09-06-2007, 00:55
scusa l'ignoranza, ma cos'è una maschera?

wisher
09-06-2007, 10:15
Una maschera è ad esempio un numero binario in cui hai un uno e il resto zero.

Puoi contare gli zeri facendo una and bit a bit con il tuo dato, di volta in volta spostando l'uno nella maschera. Se l'and ti restituisce 0 hai uno zero nella posizione indicata dalla maschera

Un esempio:
numero
10100

Maschera (Al primo passaggio)
100

101 and 100=100->al primo posto non c'è uno zero

Shift sulla maschera 010
101 and 010=000->al secondo posto c'è uno zero, incremento il contatore

Shift sulla maschera 001
101 and 001=001->al terzo posto non c'è uno zero

andbin
09-06-2007, 13:59
devo fare un esercizio in assembly, solo che non ho la piu pallida idea di come, il testo dice: " data una word contare il numero di bit a "0""Ci sono diverse strade per fare questo:

Soluzione A:
Utilizzi una "maschera", cioè un valore in cui c'è sempre solo un bit a '1' che sposti verso una direzione che scegli tu. Fai quindi una AND tra questa maschera e il tuo valore di input. Il risultato sarà un valore di 0 o diverso da 0. Quindi ti basta contare quante volte ottieni un valore di 0.
Naturalmente si può anche fare lo shift sul tuo valore di input e tenere ferma la maschera.

Soluzione B:
A dire il vero una maschera non servirebbe nemmeno se si lavora in assembly. Già ... perché basta tenere presente che quando si fa uno shift, il bit che "esce" va a finire nel flag di "carry". Pertanto ti basta fare un ciclo, shiftare il tuo valore di input e controllare il flag di carry.

Soluzione C:
Ci sarebbe un'altra soluzione che sfrutta un trucchetto forse non molto noto. È possibile eliminare il primo bit '1' più a destra (in qualunque posizione sia) facendo X AND (X-1). Questo permetterebbe di contare i bit a '1' (ovviamente facendo un ciclo). Se a te serve contare i bit a '0' farai N-c dove N è il numero totale dei bit e c il conto dei bit a '1'.
Tra l'altro questa è la soluzione più veloce se ci sono pochi bit a '1' nel valore.

Dr.Speed
09-06-2007, 17:29
Ci sono diverse strade per fare questo:

Soluzione A:
Utilizzi una "maschera", cioè un valore in cui c'è sempre solo un bit a '1' che sposti verso una direzione che scegli tu. Fai quindi una AND tra questa maschera e il tuo valore di input. Il risultato sarà un valore di 0 o diverso da 0. Quindi ti basta contare quante volte ottieni un valore di 0.
Naturalmente si può anche fare lo shift sul tuo valore di input e tenere ferma la maschera.

Soluzione B:
A dire il vero una maschera non servirebbe nemmeno se si lavora in assembly. Già ... perché basta tenere presente che quando si fa uno shift, il bit che "esce" va a finire nel flag di "carry". Pertanto ti basta fare un ciclo, shiftare il tuo valore di input e controllare il flag di carry.

Soluzione C:
Ci sarebbe un'altra soluzione che sfrutta un trucchetto forse non molto noto. È possibile eliminare il primo bit '1' più a destra (in qualunque posizione sia) facendo X AND (X-1). Questo permetterebbe di contare i bit a '1' (ovviamente facendo un ciclo). Se a te serve contare i bit a '0' farai N-c dove N è il numero totale dei bit e c il conto dei bit a '1'.
Tra l'altro questa è la soluzione più veloce se ci sono pochi bit a '1' nel valore.
la soluzione B mi sembra la piu facile, pero come posso controllare il CF? comparandolo mi esce un errore, c'e un istruzione apposita?




grazie ad entrambi per le spiegazioni molto dettagliate:)

andbin
09-06-2007, 17:39
la soluzione B mi sembra la piu facile, pero come posso controllare il CF? comparandolo mi esce un errore, c'e un istruzione apposita?Innanzitutto, visto che non l'hai specificato fin dall'inizio, di quali processori stiamo parlando?? x86?

Nell'assembly x86 c'è il salto condizionato JC, basato appunto sul carry. A partire dai 386 (ormai superati da un pezzo ;) ) puoi usare SETC r/m8, in base al carry assegna 1 oppure 0 al registro o locazione specificata. Ti può servire appunto come valore da aggiungere al tuo conteggio ... e nota, evita un salto condizionato.

Dr.Speed
09-06-2007, 17:43
si, scusami stiamo parlando di x86 :)

repne scasb
09-06-2007, 20:35
mov ax,[value]
mov cx,10h
xor dx,dx
loop_zbit:
shr ax,1h
cmc
adc dl,dh
loop loop_zbit