Operație pe biți

schimbările de biți sunt uneori considerate operații pe biți, deoarece tratează o valoare ca o serie de biți mai degrabă decât ca o cantitate numerică. În aceste operații, cifrele sunt mutate sau deplasate spre stânga sau spre dreapta. Registrele dintr-un procesor de computer au o lățime fixă, astfel încât unii biți vor fi „deplasați” din registru la un capăt, în timp ce același număr de biți sunt „deplasați” de la celălalt capăt; diferențele dintre operatorii de schimbare a biților constau în modul în care determină valorile biților deplasați.

Bit adresingedit

dacă lățimea registrului (frecvent 32 sau chiar 64) este mai mare decât numărul de biți (de obicei 8) al celei mai mici unități adresabile (element atomic), denumit frecvent octet, operațiile de schimbare induc o schemă de adresare pe biți.Ignorând efectele limită la ambele capete ale registrului, operațiile de schimbare aritmetică și logică se comportă la fel, iar o schimbare cu 8 poziții de biți transportă modelul de biți cu 1 poziție de octet în felul următor:

  • comanda Little-endian:
o schimbare la stânga cu 8 poziții mărește adresa octetului cu 1
  • comanda Little-endian:
o schimbare dreapta de 8 poziții scade adresa octet de 1
  • big-endian comanda:
o schimbare la stânga cu 8 poziții scade adresa octetului cu 1
  • big-endian comanda:
o schimbare dreapta de 8 poziții crește adresa octet de 1

aritmetica shiftEdit

Articol principal :aritmetica shift
deplasare aritmetică stângă

schimbare aritmetică corectă

într-o schimbare aritmetică, biții care sunt deplasați din ambele capete sunt aruncați. Într-o schimbare aritmetică stângă, zerourile sunt deplasate în dreapta; într-o schimbare aritmetică dreaptă, bitul semnului (MSB în complementul doi) este deplasat în stânga, păstrând astfel semnul operandului.

acest exemplu folosește un registru pe 8 biți, interpretat ca complementul lui doi:

 00010111 (decimal +23) LEFT-SHIFT= 00101110 (decimal +46)
 10010111 (decimal −105) RIGHT-SHIFT= 11001011 (decimal −53)

în primul caz, cifra din stânga a fost deplasată după sfârșitul registrului, iar un nou 0 a fost mutat în poziția din dreapta. În cel de-al doilea caz, cel mai din dreapta 1 a fost mutat (poate în steagul de transport), iar un nou 1 a fost copiat în poziția din stânga, păstrând semnul numărului. Schimbările Multiple sunt uneori scurtate la o singură schimbare cu un număr de cifre. De exemplu:

 00010111 (decimal +23) LEFT-SHIFT-BY-TWO= 01011100 (decimal +92)

o deplasare aritmetică stângă cu n este echivalentă cu înmulțirea cu 2N (cu condiția ca valoarea să nu depășească), în timp ce o deplasare aritmetică dreaptă cu n a valorii complementului unui doi este echivalentă cu împărțirea cu 2n și rotunjirea spre infinit negativ. Dacă numărul binar este tratat ca complement al celor, atunci aceeași operație de schimbare dreapta are ca rezultat împărțirea cu 2n și rotunjirea spre zero.

schimbare logică

Articol principal: Schimbare logică
stânga schimbare logică

schimbare logică corectă

într-o schimbare logică, zerourile sunt deplasate pentru a înlocui biții aruncați. Prin urmare, schimbările logice și aritmetice din stânga sunt exact aceleași.

cu toate acestea, ca logic dreapta-shift inserează valoarea 0 biți în bitul cel mai semnificativ, în loc să copieze bitul semnului, este ideal pentru numere binare nesemnate, în timp ce aritmetica dreapta-shift este ideal pentru numerele binare complementare semnate de doi.

schimbare Circularăedit

informații suplimentare: schimbare circulară

o altă formă de schimbare este schimbarea circulară, rotația pe biți sau rotația bitului.

Rotațiemodificare

deplasare circulară stânga sau rotire

schimbare circulară dreapta sau rotire

în această operație, uneori numită rotire fără transport, biții sunt” rotiți ” ca și cum capetele din stânga și din dreapta ale registrului ar fi unite. Valoarea care este deplasată în dreapta în timpul unei schimbări la stânga este orice valoare a fost deplasată în stânga și invers pentru o operație de schimbare la dreapta. Acest lucru este util dacă este necesar să se păstreze toți biții existenți și este frecvent utilizat în criptografia digitală.

Rotate through carrymodificare

Rotire stânga prin carry

rotiți dreapta prin transport

rotire prin transportare este o variantă a operației de rotire, unde bitul care este deplasat (la ambele capete) este vechea valoare a steagului de transport, iar bitul care este deplasat (la celălalt capăt) devine noua valoare a steagului de transport.

o singură rotire prin transport poate simula o schimbare logică sau aritmetică a unei poziții prin configurarea steagului de transport în prealabil. De exemplu, dacă steagul carry conține 0, atunci x RIGHT-ROTATE-THROUGH-CARRY-BY-ONE este o schimbare logică la dreapta, iar dacă steagul carry conține o copie a bitului semnului, atunci x RIGHT-ROTATE-THROUGH-CARRY-BY-ONE este o schimbare aritmetică la dreapta. Din acest motiv, unele microcontrolere, cum ar fi PICs low end, au doar rotire și rotire prin transportare și nu vă deranjați cu instrucțiuni aritmetice sau logice de schimbare.

rotirea prin transportare este utilă în special atunci când efectuați schimbări pe numere mai mari decât dimensiunea cuvântului nativ al procesorului, deoarece dacă un număr mare este stocat în două registre, bitul care este deplasat de la un capăt al primului registru trebuie să intre la celălalt capăt al celui de-al doilea. Cu rotate-through-carry, acel bit este” salvat ” în steagul de transport în timpul primei schimburi, gata să se deplaseze în timpul celei de-a doua schimburi fără nicio pregătire suplimentară.

în limbi la nivel înaltedit

informații suplimentare: Circular de schimbare § circulara de punere în Aplicare schimburi

C-familyEdit

În C-familie de limbi, logic shift operatorii sunt „<<” pentru shift stânga și „>>” pentru schimbare. Numărul de locuri de schimbat este dat ca al doilea argument operatorului. De exemplu,

x = y << 2;

atribuie x rezultatul deplasării y spre stânga cu doi biți, ceea ce este echivalent cu o înmulțire cu patru.

schimbările pot avea ca rezultat un comportament definit de implementare sau un comportament nedefinit, deci trebuie să aveți grijă atunci când le utilizați. Rezultatul schimbării cu un număr de biți mai mare sau egal cu dimensiunea cuvântului este un comportament nedefinit în C și C++. Schimbarea la dreapta o valoare negativă este definită de implementare și nu este recomandată de buna practică de codificare; rezultatul schimbării la stânga a unei valori semnate este nedefinit dacă rezultatul nu poate fi reprezentat în tipul de rezultat.

în C#, dreapta-shift este o schimbare aritmetică atunci când primul operand este un int sau lung. Dacă primul operand este de tip uint sau ulong, schimbarea din dreapta este o schimbare logică.

circulare shiftsEdit

familia C de limbi nu are un operator de rotire, dar unul poate fi sintetizat din operatorii de schimbare. Trebuie să aveți grijă să vă asigurați că declarația este bine formată pentru a evita comportamentul nedefinit și atacurile de sincronizare în software cu cerințe de securitate. De exemplu, o implementare naivă care stânga rotește o valoare nesemnată pe 32 de biți x cu n poziții este pur și simplu:

uint32_t x = ..., n = ...;uint32_t y = (x << n) | (x >> (32 - n));

cu toate acestea, o schimbare cu 0 biți are ca rezultat un comportament nedefinit în expresia mâinii drepte (x >> (32 - n)) deoarece 32 - 0 este 32 și 32 este în afara intervalului inclusiv. O a doua încercare ar putea duce la:

uint32_t x = ..., n = ...;uint32_t y = n ? (x << n) | (x >> (32 - n)) : x;

în cazul în care suma de schimbare este testată pentru a se asigura că nu introduce un comportament nedefinit. Cu toate acestea, sucursala adaugă o cale suplimentară de cod și prezintă o oportunitate pentru analiza și atacul de sincronizare, ceea ce adesea nu este acceptabil în software-ul de înaltă integritate. În plus, codul compilează mai multe instrucțiuni de mașină, care este adesea mai puțin eficient decât instrucțiunea nativă a procesorului.

pentru a evita comportamentul nedefinit și ramurile sub GCC și zăngănit, se recomandă următoarele. Modelul este recunoscut de mulți compilatori, iar compilatorul va emite o singură instrucțiune de rotire:

uint32_t x = ..., n = ...;uint32_t y = (x << n) | (x >> (-n & 31));

există, de asemenea, intrinseci specifice compilatorului care implementează schimbări circulare, cum ar fi _rotl8, _rotl16, _rotr8, _rotr16 în Microsoft Visual C++. Zăngăni oferă unele roti intrinseci pentru compatibilitate Microsoft care suferă problemele de mai sus. GCC nu oferă roti intrinseci. Intel oferă, de asemenea, intrinseci x86.

JavaEdit

în Java, toate tipurile întregi sunt semnate, astfel încât operatorii „<<” și „>> ” efectuează schimburi aritmetice. Java adaugă operatorul ” >>>” pentru a efectua schimburi logice la dreapta, dar din moment ce operațiile logice și aritmetice de schimbare la stânga sunt identice pentru un număr întreg semnat, nu există un operator „<<< ” în Java.

mai multe detalii despre operatorii java shift:

  • operatorii << (schimbare stânga), >> (schimbare dreapta semnată) și >>> (schimbare dreapta nesemnată) se numesc operatori de schimbare.
  • tipul expresiei shift este tipul promovat al operandului din stânga. De exemplu, aByte >>> 2 este echivalent cu ((int) aByte) >>> 2.
  • dacă tipul promovat al operandului din stânga este int, doar cei cinci biți de ordinul cel mai mic ai operandului din dreapta sunt folosiți ca distanță de deplasare. Este ca și cum operandul din dreapta ar fi supus unui operator logic și bit & cu valoarea măștii 0x1f (0b11111). Prin urmare, Distanța de schimbare utilizată efectiv este întotdeauna în intervalul 0-31, inclusiv.
  • dacă tipul promovat al operandului din stânga este lung, atunci doar cei șase biți de ordinul cel mai mic ai operandului din dreapta sunt folosiți ca distanță de deplasare. Este ca și cum operandul din dreapta ar fi supus unui operator logic și bit & cu valoarea măștii 0x3f (0b111111). Prin urmare, Distanța de deplasare utilizată efectiv este întotdeauna cuprinsă între 0 și 63, inclusiv.
  • valoarea n >>> s este N poziții de biți s deplasate la dreapta cu extensie zero.
  • în operațiile de biți și schimbare, tipul byteeste implicit convertit în int. Dacă valoarea octetului este negativă, bitul cel mai mare este unul, atunci Cele sunt folosite pentru a umple octeții suplimentari din int. Deci octet b1 = -5; int i = b1 | 0x0200; va avea ca rezultat i = = -5.

JavaScriptEdit

JavaScript utilizează operațiuni bitwise pentru a evalua fiecare dintre două sau mai multe unități loc la 1 sau 0.

PascalEdit

în Pascal, precum și în toate dialectele sale (cum ar fi Object Pascal și Standard Pascal), operatorii logici de schimbare stânga și dreapta sunt „shl” și ” shr„, respectiv. Chiar și pentru numere întregi semnate, shr se comportă ca o schimbare logică și nu copiază bitul semnului. Numărul de locuri de schimbat este dat ca al doilea argument. De exemplu, următoarele atribuie x rezultatul deplasării y spre stânga cu doi biți:

x := y shl 2;

Lasă un răspuns

Adresa ta de email nu va fi publicată.

More: