Valutazione 4.87/ 5 (100.00%) 5838 voti

Condividi:        

Programma Assembler conteggio dei bit a 1 in una variabile

Problemi di HTML? Di PHP, ASP, .NET, JSP, Perl, SQL, JavaScript, Visual Basic..?
Vuoi realizzare programmi in C, C++, Java, Ruby o Smalltalk, e non sai da che parte cominciare?
Entra qui e troverai le risposte!

Moderatori: Triumph Of Steel, archimede

Programma Assembler conteggio dei bit a 1 in una variabile

Postdi stex » 12/03/09 13:34

Vorrei sapere come faccio a fare questo programma in assembler
TESTO: Scrivere una MACRO assembly 8086 che consenta di calcolare il numero di bit a 1 contenuti nella word di memoria VAR.

Domanda: Come faccio a prendere in esame i singoli bit di una word? Con quali istruzioni?
POTETE AIUTARMI GRAZIE
Motheborard: ASUS P5Q
Processore: INTEL Q9550
Memorie: Corsair DDR2 corsair 800mhz cl4
Scheda video: ATI gainward 4850 golden sample
Alimentatore: Corsair 550 watt
Case: cooler master gladiator 600
stex
Utente Junior
 
Post: 42
Iscritto il: 21/03/05 21:38

Sponsor
 

Re: Programma Assembler conteggio dei bit a 1 in una variabile

Postdi Dylan666 » 13/03/09 10:38

Avatar utente
Dylan666
Moderatore
 
Post: 38040
Iscritto il: 18/11/03 16:46

Re: Programma Assembler conteggio dei bit a 1 in una variabile

Postdi zello » 17/03/09 14:56

Tutto molto bello; trovo che ridurre qualche salto condizionale sia meglio (non testato, vado a logica)
Codice: Seleziona tutto
; ax contiene la word cui contare i bits, la parte alta di eax è ignorata
; in uscita, eax contiene il numero di bits
; i registri vengono preservati (tutti meno eax, anche edx, che di solito si presume non preservato), i flags
; vengono distrutti (volendo basta un push in più, ma è prassi considerarli invalidi dopo una chiamata di procedura)

  push ebx
  push ecx
  push edx
  mov ecx, 10h    ; 16 bit da testare
  xor edx,edx      ; azzero edx e ebx
  mov ebx,edx
l0:
  shr eax,1      ; shifto a destra, l'ultimo bit finisce nel carry
  setc bl          ; imposto bl -> 0 se l'ultimo bit era 0, a 1 se l'ultimo bit era a 1
  add edx,ebx  ; addiziono a edx
  loopnz l0       ; ripeto il loop 16 volte
  mov eax, edx
  pop edx
  pop ecx
  pop ebx
  ret
Il faut être toujours ivre. Tout est là : c'est l'unique question. Pour ne pas sentir l'horrible fardeau du Temps qui brise vos épaules et vous penche vers la terre,il faut vous enivrer sans trêve...
Avatar utente
zello
Moderatore
 
Post: 2351
Iscritto il: 06/05/02 13:44

Re: Programma Assembler conteggio dei bit a 1 in una variabile

Postdi stex » 17/03/09 16:32

Scusa ma non capisco cosa fa l'istruzione SETC ?

Io ho anche questa soluzione dimme se va bene:

CONTEGGIO MACRO var

MOV AX,var
XOR DX,DX
MOV CX,16d; Inserisco il valore decimale 16 in CX
N_VOLTE: SHL AX,1
TEST AX,1; simula l'AND
JE AGGIUNGI
LOOP N_VOLTE
AGGIUNGI: ADD DX,1
LOOP N_VOLTE
--Mi potresti dire con precisione che differenza c'è tra fare l'istruzione AND o TEST? Cosa cambia?
-- Per comparare i bit di una word con il bit di carry ci sono altre istruzioni per l'8086?
Motheborard: ASUS P5Q
Processore: INTEL Q9550
Memorie: Corsair DDR2 corsair 800mhz cl4
Scheda video: ATI gainward 4850 golden sample
Alimentatore: Corsair 550 watt
Case: cooler master gladiator 600
stex
Utente Junior
 
Post: 42
Iscritto il: 21/03/05 21:38

Re: Programma Assembler conteggio dei bit a 1 in una variabile

Postdi zello » 17/03/09 23:38

Allora, intanto ci ho pensato anch'io, e setcond (poi ti spiego cosa fa) è un tantinello inutile qui.
Questo ciclo a 16 bit funziona tranquillamente:
Codice: Seleziona tutto
bit_count:
     push bp
     mov bp,sp
     push cx
     push dx
     mov dx, w[bp+4]
     xor ax,ax
 l0: 
     shr dx,1
     adc ax,0
     loop l0
   
     pop dx
     pop cx
     pop bp
     ret 2

Qualche nota:
- ho utilizzato a86, che è un ottimo assembler a 16 bit che usavo quando ancora non mi cresceva la barba (la data di creazione del file sul disco è il 24/09/1995, tanto per darti un'idea). E' meno brigoso e assai più veloce di qualsiasi nasm, tasm o masm. Ciò detto, se cambi il w[] in word ptr[] ottieni un risultato compilabile anche con gli altri assembly
- la procedura si aspetta di essere chiamata con una word sullo stack che rappresenta la variabile di cui contare i bit, e scarta la word al momento del ritorno (la cosiddetta convenzione di chiamata pascal). Se la chiami dal C, sostituisci il ret 2 con un ret (in C è il chiamante che deve risistemare lo stack, non la procedura chiamata; vedi anche esempio successivo)
- il return value è in ax (anche questo è uno standard di chiamata)
- la procedura funziona così: la funzione shr shifta i bit di un registro verso destra, e l'ultimo bit finisce nel carry. L'istruzione adc somma il secondo operando al primo, e aggiunge anche il bit di carry. Scrivere adc ax, 0 significa aggiungere il bit di carry a ax
- la tua procedura non va bene: intanto è incasinata, e poi se shifti prima del confronto conti un bit in meno con i numeri dispari. Una procedura alternativa potrebbe essere del tipo (in ax ho quello che conto, in dx quanti bit sono settati - non è standard ma è l'uso che fai tu dei registri)
Codice: Seleziona tutto
...
xor dx,dx
mov cx, 10h
l0:
    test ax, 1
    jz .skip
    inc dx
skip:
    shr ax,1
    loop l0

Questo codice non è brutto, ma ha un salto condizionale (jz...), che manda in difficoltà la pipeline dei pentium (nel senso: va bene la branch prediction, va bene che è tutto in cache, ma meno salti condizionali ci infili nel codice e meglio è).
Ah, e - a meno di motivi particolari - usa inc ("INCrement") al posto di add <registro>, 1. In termini di velocità è lo stesso (2 cicli se non ci sono accessi in memoria, almeno così dice il manuale del 386), ma è almeno un byte in meno che consumi di memoria.

Ultima cosa: se il ciclo è a 32 bit, il codice - che poi è analogo - è questo:
Codice: Seleziona tutto
push ecx
      push edx
      mov edx,dword ptr[esp+12]
      mov ecx,32
      xor eax,eax
l0:
      shr edx,1
      adc eax,0
      loop l0
      pop edx
      pop ecx
      ret

(questo l'ho testato con il visual c++; visto che la chiamata era in convenzione C, non ho il ret 2; tutti i registri sono a 32 bit; non creo il frame (tanto posso indirizzare direttamente esp, senza bisogno di scomodare ebp), e visto che non mi costa nulla conto i bit in una double word al posto che in una word.

Infine:
Scusa ma non capisco cosa fa l'istruzione SETC ?

Setc (più in generale: SETcond) setta il suo argomento, che è un puntatore ad un byte di memoria o un registro di un byte, a 0 o a 1 a seconda che la cond sia verificata.
SETZ al -> al=1 se lo zero flag è settato, 0 altrimenti
E' un'istruzione presente a partire dal 386 (quando ha cominciato ad avere senso limitare i salti condizionali).
Mi potresti dire con precisione che differenza c'è tra fare l'istruzione AND o TEST?

AND - ovviamente - fa l'and binario fra i due operandi, e il primo operando è modificato di conseguenza.
AND eax, ebx è l'equivalente di eax = eax & ebx, dove l'operatore & confronta bit a bit i due operandi, e setta ogni bit secondo la classica regola:
- se due bit corrispondenti sono a 1, il risultato è 1
- altrimenti il risultato è 0
Nel contempo, viene settato lo zero flag se il risultato dell'operazione è 0; il carry flag invece viene comunque sempre resettato (questa è un'eredità dello Z80, direi, buon vecchio ZX spectrum -> non c'era l'istruzione di azzeramento esplicito del carry - tipo CCF dell'80x86 - e quindi "AND A" era un buon modo di azzerarlo).
TEST è identico ad and, ma non influenza il risultato, solo i flags.
TEST EAX, EBX esegue eax & ebx e butta via il risultato, condizionando solo lo zero e il carry flag.
Nel tuo caso DEVI usare test, se usi AND azzeri per definizione tutti i bit di AX meno l'ultimo.

(ah, che bello, un po' di assembly. Voi mi fate sentire giovane, ragazzi)

Ciao.
Il faut être toujours ivre. Tout est là : c'est l'unique question. Pour ne pas sentir l'horrible fardeau du Temps qui brise vos épaules et vous penche vers la terre,il faut vous enivrer sans trêve...
Avatar utente
zello
Moderatore
 
Post: 2351
Iscritto il: 06/05/02 13:44


Torna a Programmazione


Topic correlati a "Programma Assembler conteggio dei bit a 1 in una variabile":


Chi c’è in linea

Visitano il forum: Nessuno e 6 ospiti