La Smette di Piovere ? - by Dreadnaut (c) 2002

-- Bit, maschere e shift. Ovvero vari pensieri formulati su 40km di ferrovia un pomeriggio che come tanti altri tornavo a casa -- ver 0.2
Il pascal (come quasi tutti i linguaggi, non esaltiamoci :-) ) offre una serie di operatori logici, che usualmente sono utilizzati per concatenare espressioni binarie. Oltre a questo, se applicati a variabili intere (shortint, integer, longint, byte e word), essi lavorano anche come `operatori bit a bit' [ in C e dialetti la differenza fra operatori logici e bitwise e' piu' marcata: '&' e' l'and bit a bit mentre '&&' quello logico, e cosi' via...]

-- Bitwise Operators -- Gli operatori bit a bit considerano le variabili intere, di qualsiasi dimensione esse siano, come `array di bit', ed eseguono su di esse le basilari operazioni booleane: AND (e , disgiunzione, moltipl.) vera se entrambi gli operandi sono veri OR (o, congiunzione, somma) vera se almeno un operando e' vero NOT (non, negazione) vera se falsa, falsa se vera XOR (or esclusivo, disuguaglianza) vera se uno vero, ma non entrambi ok... fin qua niente di trascendentale, ma mi serviva elencarli con tutti i loro malvagi significati: ogni operatore ha piu' di un uso possibile a seconda di come si considerano i loro operandi, come stati logici o come numeri binari... e' utile averlo presente. Mischiando questa visione delle variabili intere con il `normale' significato numerico che gli diamo, si possono ottenere un sacco di cose. - AND - L'and e' l'operatore di `taglio': con esso e' possibile selezionare parti di una variabile intera e annullarne altre senza doverci preoccupare del loro valore. Questo si ottiene utilizzando una `maschera', cioe' un numero binario che un po' come un foglio di carta con dei buchi ci permette di vedere o no quello che c'e' sotto. Ad esempio, utilizzando come maschera `00001111' ( $f, o meglio 15 ) e calcolando x AND maschera otteniamo i quattro bit bassi di x, qualsiasi sia il loro valore: questo puo' essere utilizzato per prendere ad esempio la parte `foreground' dall'attributo di un carattere in modalita' testo, ma allo stesso tempo per l'operazione di mod 16. Le op. bitwise hanno sempre piu' di un significato. L'and equivale al modulo per potenze di due: x mod n = x and (n-1) se n = 2^k Per sapere se un numero e' dispari basta fare x and 1, cioe' chiediamo se il primo bit e' 1 ( il primo bit vale 2^0 quindi se e' attivo il numero e' dispari), ed infatti l'operazione aritmetica equivalente e' x mod 2. - OR - L'or e' la somma, l'unione: possiamo unire due valori, oppure due insiemi di bit sia disgiunti che sovrapposti. Sempre parlando di attributi sfondo piu' colore: attrib := (blinking shl 7) or (sfondo shl 4) or (testo); {degli shift si parla dopo...} ed equivale ad attrib := blinking * 128 + sfondo * 16 + testo; ma rispecchia il modo in cui possiamo estrarre (con l'and) i vari valori dal byte degli attributi. - NOT - beh del not non mi sembra necessario parlare piu' di tanto... e' l'operatore che inverte ogni singolo bit dell'argomento, quindi ci da' il "negativo" (eh si, anche se parliamo di colori...) - XOR - Il mistico or esclusivo, base della crittografia [ l'one-time pad e' l'unico metodo veramente sicuro... ma in fondo e' inapplicabile :-) ] puo' essere usato per ottenere l'effetto del not su singoli bit, sempre utilizzando maschere: poniamo ad 1 i bit che vogliamo invertire nel nostro numero 11111111 xor 10000001 = 01111110 e cosi' via... Inoltre x xor x da sempre 0, quindi si puo' usare per azzerare variabili, soprattuto in asm, perche' e' piu' veloce di un'operazione del tipo: mov <registro>,0 -- Altre operazioni -- - Operatori di shift - dato che gli operatori bitwise vedono gli interi come una fila di bit, puo' essere utile avere la possibilita' di spostare a destra o a sinistra queste file. Gli operatori di shift ci danno questa possibilita': x shr n (Shift Right) sposta a destra di n bit la rappresentazione di x x shl n (Shift Left) invece sposta a sinistra di n bit poiche' lavoriamo in binario, shiftare equivale a promuovere (sx) o a retrocedere (dx) i bit a una potenza di 2 superiore (o inferiore), e quindi x shr n = x / 2^n x shl n = x * 2^n N.B. lo shift non e' `circolare': i bit che `escono' da una parte del numero vanno persi e dall'altra parte vengono aggiunti solo zeri a.e. 15 shl 3 = 00001111 spostato a sx di 3 = 01111000 - Hi & Lo - quando si lavora su word e integer puo' essere utile avere soltanto una delle due meta' del numero: Hi() e Lo() restituiscono rispettivamente il byte alto e quello basso della variabile. Non so' come siano implementate, ma equivalgono a: Hi := x shr 8 Lo := x and $ff quindi in generale per sicurezza, onde evitare una `costosissima' chiamata di funzione, io uso sempre le versioni shr/and :-) -- Perche' bitwise -- Gli operatori bit a bit inizialmente possono sembrare assurdi e spaventosi, e in effetti lo sono, ma con un po' di pratica si puo' imparare a mischiarli a quelli aritmetici e rendere il codice piu' rapido e compatto [ anche se illeggibile, ma chissenefrega :-) ] Un esempio puo' essere la conversione in esadecimale: ci vorrebbero divisioni, sottrazioni e cicli per trasformare un word in quattro caratteri, ma utilizzando shift e and si ottiene una formula esplicita: const HxSymb: array [0..15] of Char = '0123456789ABCDEF'; function Hex(n: word): string; begin Hex := HxSymb[n shr 12 and $F] + HxSymb[n shr 8 and $F] + HxSymb[n shr 4 and $F] + HxSymb[n and $F]; end; Zero cicli, zero moltiplicazioni: solo shift ed and, operazioni che sono a livello macchina e richiedono un solo ciclo di processore (piu' vabbeh tutto quello che c'e' in piu' per le variabili, le stringhe, le somme) { -------------------------------------------------------------------------- } Topic nell'help del TP7 - Bitwise-operators [vs Boolean-operators], Integer types, Precedence [of Operators] - SHL - Shift Left Operator (...SHL...) SHR - Shift Right Operator (...SHR...) AND - Bitwise AND [ idem per gli altri operatori ] { -------------------------------------------------------------------------- } -eof- 08/05/02 - (c) 2002, Dreadnaut production Il contenuto di questo documento e' da considerarsi esclusivamente invenzione dell' autore, ogni riferimento a cose o persone realmente esistenti e' puramente casuale e non voluto.