Sunteți pe pagina 1din 6

Operatori la nivel bit

Deoarece avem nevoie n multe cazuri sa se realizeze o prelucrare la nivel de bit s-a introdus aceasta clasa de operatori. Sunt folositi n special pentru scrierea de cod pentru controlul unor dispozitive fizice interne sau externe masinii. Fac parte din categoria operatorilor binary, exceptie facnd cel de inversare a bitilor. Daca consideram trei variabile a, b si c pe n biti si notam cu ai, bi si ci bitii de rang i atunci: SI logic bit cu bit cu simbolul & c=a&b este echivalent cu ci=ai*bi cu i = 0n-1; SAU logic bit cu bit cu simbolul | c=a|b este echivalent cu ci= (ai+,bi) ( ai*bi) cu i = 0n-1; SAU Exclusiv logic bit cu bit cu simbolul ^ c=a^b este echivalent cu ci=aibi cu i = 0n-1 (adunare cu neglijarea transportului); Negare logica bit cu bit cu simbolul ~ c=~a este echivalent cu ci= ai cu i = 0n-1; Deplasare la dreapta cu n biti >> a=a>>p este echivalent cu ai-p=ai pentru i = n-1p si ai =0 pentru i=n1n-p-1; Deplasare la stnga cu n biti << a=a<<p este echivalent cu ai+p=ai pentru i = n-10 si ai =0 pentru i=0p-1. Relativ la acesti operatori trebuie facute o serie de observatii. n primul rnd trebuie avuta grija ca sa nu fie confundati cu operatorii logici folositi n cazul evaluarii unei expresii logice complexe. n al doilea rnd o alta aplicatie imediata este posibilitatea analizei sau prelucrarii separate a valorilor numai pentru anumiti biti din interiorul unui octet prin folosirea lucrului cu masti. O masca reprezinta acea valoare calculata astfel nct prin conjunctia ei cu o variabila cuvnt oarecare, conjunctie realizata cu un operator logic la nivel de bit sa se poata prelucra numai anumiti biti din respectiva variabila. Este clar ca masca va avea acelasi numar de octeti ca si variabila procesata. Dat fiind modul de stocare, aceasta tehnica poate fi aplicata doar variabilelor de tipul char sau int fara semn. Sa vedem care sunt operatiile cele mai folosite: pentru inversarea valorii unui bit vom tine cont de relatiile: x0=x si x1= x ; pentru anularea valorii unui bit vom tine cont de relatiile: x*0=0 si x*1=x. Exista mai multe cazuri tipice: cnd se doreste doar prelucrarea unui singur bit din variabila; cnd se doreste prelucrarea mai multor biti izolati; cnd se doreste prelucrarea unor grupari de biti (aici sunt mai eficiente uniunile).

Prelucrarea unui singur bit dintr-o variabila Se utilizeaza daca se doreste numai aflarea valorii bitului de pe pozitia i. Pentru aceasta va trebui sa anulam valorile pentru restul bitilor. Vom realiza astfel un produs bit cu bit ntre o masca care are 1 pe pozitia i si 0 n rest. Daca rezultatul este diferit de 0 nseamna ca bitul de pe pozitia i este 1 si invers. De exemplu, pentru un octet putem testa bitul de pe pozitia 3 astfel:
#define MASK 0x04 unsigned char data; // data din care trebuie verificat bitul de pe pozitia 3 if (data&MASK) puts("Al treile bit este 1"); else puts("Al treile bit este 0");

Daca dorim sa inversam valoarea acestuia vom folosi aceeasi masca numai ca vom face un sau exclusiv bit cu bit ntre masca si variabila. Deci pentru exemplul anterior am putea scrie:
data=data^MASK;

Prelucrarea mai multor biti izolati dintr-o variabila Dupa cum s-a observat indiferent ca fac ispectie sau modificare folosesc aceasi masca. n aceasta situatie deoarece s-ar putea sa trebuiasca sa fac n acelasi moment operatii diferite cu fiecare din bitii vizati rezulta ca cel mai eficeint este sa construiesc cte o masca pentru fiecare bit iar prelucrarea se face ca n cazul anterior. Prelucrarea gruparilor de biti n acest caz este mult mai recomandata folosirea uniunilor despre care se va discuta mai ncolo. Totusi presupunnd ca se va lucra pe un compilator de C fara respectiva facilitate sa vedem cum se izoleaza si se prelucreaza un grup de biti. Sa consideram ca pentru un octet dorim sa lucram cu bitii 4, 5 si 6. Pentru cazul inspectiei valorii numerice din ei:
#define MASK 0x40 #define MASK1 0x8f unsigned char data,temp; temp=data&MASK; temp=temp>>4; // am izolat cei trei biti // am obtint valoare numerica stocata n ei

Pentru cazul initializarii lor cu valoarea 5 fara a modifica restul bitilor din data vom proceda astfel:
#define MASK 0x40 unsigned char data,temp=5; temp=temp<<4; data=data&MASK1; data=data|temp; // pregatim valoarea pe pozitia corecta // punem pe 0 numai bitii de pe pozitiile 3, 4 si 5 // depunem efectiv noua valoare n pozitia dorita

Pentru cazurile n care exista nevoia realizarii unor operatii de deplasare cu recirculare a bitilor se pot folosi urmatoarele implementari: a) pentru deplasare la dreapta cu n pozitii cu recirculare:
#define MASK 0x0001 unsigned int data,temp for(i=0;i<n;i++) { temp=data&MASK; data=data>>1; temp=temp<<16; data=data|temp; }

Din cauza ca n lucrul cu dispozitive fizice avem nevoie de maximum de viteza a codului, n majoritatea cazului aceasta prima versiune trebuie reanalizata. Se observa ca este inutil sa facem 16 deplasari cnd stim pozitia unde trebuie reintrodusa valoarea recirculata. Este mai eficient sa mai cream o masca si astfel codul devine:
#define MASK 0x0001 #define MASK1 0x8000 unsigned int data,temp for(i=0;i<n;i++) { temp=data&MASK; data=data>>1; if(temp) data=data|MASK1; }

b) pentru deplasare la stnga cu n pozitii cu recirculare:


#define MASK 0x0001 #define MASK1 0x8000 unsigned int data,temp for(i=0;i<n;i++) { temp=data&MASK1; data=(int)data<<1; // ca sa fim absolut siguri ca se pierde if(temp) data=data|MASK; }

Mai jos este prezentat un program de test pentru operatorii bit cu bit.

void main(void) { char mask; char number[6]; // tablou de 6 elemente de tip char char and,or,xor,inv,index; number[0] = 0x00; // initializare n cod number[1] = 0x11; number[2] = 0x22; number[3] = 0x44; number[4] = 0x88; number[5] = 0xFF; printf("Numerele asupra carora am aplicat diverse operatii logice folosind o masca sunt: \n"); mask = 0x0F; for (index = 0;index <= 5;index++) { and = mask & number[index]; // si logic or = mask | number[index]; //sau logic xor = mask ^ number[index]; // sau exclusiv inv = ~number[index]; // not bit cu bit printf("%5x %5x %5x %5x %5x %5x\n", number[index], mask,and,or,xor,inv); } printf("\n"); mask = 0x22; for (index = 0;index <= 5;index++) { and = mask & number[index]; or = mask | number[index]; xor = mask ^ number[index]; inv = ~number[index]; printf("%5x %5x %5x %5x %5x %5x\n", number[index],mask,and,or,xor,inv); } }

1. nmultirea numerelor reprezentate n cod binar natural Fie X = 12, Y = 6. Considernd numere fara semn cu 4 biti de marime, nmultirea binara obisnuita a celor doua numere se efectueaza astfel:
1100 0110 0000 1100 1100 0000 1001000

Denmultit (12) nmultitor (6) Produse partiale Produs final (26 + 23 = 64+8 = 72)

Procesul consta din testarea succesiva a bitilor nmultitorului, ncepnd cu bitul cel mai putin semnificativ. Daca bitul testat este 1, se copiaza denmultitul, n caz contrar fiind copiate zerouri. Problema Scrieti un program C care implementeaza acest algoritm si verificati exemplul

2. nmultirea prin metoda directa Schema logica pentru nmultire prin metoda directa este prezentata n figura alaturata. Consideram X = 9, Y = -12. Executia operatiei de nmultire este ilustrata n Tabelul 1, care prezinta continutul registrelor dispozitivului de nmultire n fiecare pas al operatiei.
Tabelul 1. Executia operatiei de nmultire 9? (-12) prin metoda directa.
Pas 0 1 2 3 A 0 0000 0 0000 0 0000 + 1001 0 1001 0 0100 + 1001 0 1101 0 0110 1 0110 Q 1100 0110 0011 0011 1001 1001 1001 1100 1100 1001 1 1 0 0 0 0 B 1001 1001 1001 1001 1 1 1 Qn 1 1 1 Q0 0 0 1 N 4 3 2 Operatii Initializare Deplasare A_Q la dreapta Deplasare A_Q la dreapta Adunare denmultit Deplasare A_Q la dreapta Adunare denmultit Deplasare A_Q la dreapta Stabilire semn rezultat

Rezultatul este: 1 0110 11002 = -0110 11002 = -6Ch = -(616+12) = -108. Problema Scrieti un program C care implementeaza acest algoritm si verificati exemplul 3. nmultirea prin metoda Booth

Consideram X = 13, Y = -10. Exprimarea binara a acestor numere n C2 este urmatoarea: X = 0 11012 Y = 1 01102 Scaderea denmultitului se efectueaza prin adunarea complementului fata de 2 al acestuia: X (C2) = X = 1 00112
Tabelul 2. Executia operatiei de nmultire 13 ? (10) prin metoda Booth.
Pas 0 1 2 A 0 0000 0 0000 + 1 0011 1 0011 1 1001 1 1100 + 0 1101 0 1001 0 0100 + 1 0011 1 0111 1 1011 Q 1 0110 0 1011 0 1011 1 0101 1 1010 1 1010 1 1101 1 1101 1 1110 Q-1 0 0 0 1 1 1 0 0 1101 0 1 01 0 0 1101 0 1101 10 1 B 0 1101 0 1101 0 1101 11 01 3 2 Q0Q-1 00 10 N 5 4 Initializare Deplasare A_Q la dreapta Scadere denmultit Deplasare A_Q la dreapta Deplasare A_Q la dreapta Adunare denmultit Deplasare A_Q la dreapta Scadere denmultit Deplasare A_Q la dreapta Operatii

3 4

Continutul registrelor dispozitivului de nmultire n fiecare pas al operatiei este prezentat n Tabelul 2. Rezultatul este: 1 0111 11102 = -1000 00102 = -82h = -(816+2)= -130. Problema Scrieti un program C care implementeaza acest algoritm si verificati exemplul