bitskiftene betraktes noen ganger som bitvis operasjoner, fordi de behandler en verdi som en serie biter i stedet for som en numerisk mengde. I disse operasjonene flyttes sifrene, eller flyttes, til venstre eller høyre. Registre i en datamaskinprosessor har en fast bredde, så noen biter vil bli » skiftet ut «av registeret i den ene enden, mens det samme antall biter blir» skiftet inn » fra den andre enden; forskjellene mellom bitskiftoperatører ligger i hvordan de bestemmer verdiene for de skiftede bitene.
Bit addressingEdit
hvis bredden på registeret (ofte 32 eller til og med 64) er større enn antall biter (vanligvis 8) av den minste adresserbare enheten (atomelement), ofte kalt byte, gir skiftoperasjonene et adresseringsskjema på bitene.Uansett grenseeffekter i begge ender av registret, oppfører aritmetiske og logiske skiftoperasjoner det samme, og et skifte med 8 bitposisjoner transporterer bitmønsteret med 1 byte-posisjon på følgende måte:
|
et venstre skift med 8 stillinger øker byte-adressen med 1 |
|
et høyre skift med 8 stillinger reduserer byte-adressen med 1 |
|
et venstre skift med 8 stillinger reduserer byte-adressen med 1 |
|
et høyre skift med 8 stillinger øker byte-adressen med 1 |
Aritmetisk skiftrediger
i et aritmetisk skifte blir biter som skiftes ut av hver ende kassert. I et venstre aritmetisk skift blir nuller skiftet inn til høyre; i et riktig aritmetisk skifte blir tegnbiten (MSB i to komplement) skiftet inn til venstre, og dermed bevare operandens tegn.
dette eksemplet bruker et 8-biters register, tolket som to komplement:
00010111 (decimal +23) LEFT-SHIFT= 00101110 (decimal +46)
10010111 (decimal −105) RIGHT-SHIFT= 11001011 (decimal −53)
i det første tilfellet ble det venstre sifferet skiftet forbi slutten av registret, og en ny 0 ble skiftet til høyre. I andre tilfelle ble høyre 1 skiftet ut (kanskje inn i bæreflagget), og en ny 1 ble kopiert til venstre posisjon, og beholdt tegn på nummeret. Flere skift blir noen ganger forkortet til et enkelt skift med et antall sifre. For eksempel:
00010111 (decimal +23) LEFT-SHIFT-BY-TWO= 01011100 (decimal +92)
et venstre aritmetisk skifte med n er ekvivalent med å multiplisere med 2n (forutsatt at verdien ikke overløper), mens et høyre aritmetisk skifte med n av en tos komplementverdi er ekvivalent med å dele med 2n og avrunde mot negativ uendelig. Hvis det binære tallet behandles som ens komplement, resulterer den samme høyre skiftoperasjonen i divisjon med 2n og avrunding mot null.
Logisk skiftrediger
Venstre logisk skift
|
Høyre logisk skift
|
i et logisk skifte blir nuller skiftet inn for å erstatte de kasserte biter. Derfor er de logiske og aritmetiske venstre skiftene nøyaktig det samme.
men som den logiske høyreforskyvningen setter inn verdien 0 biter i den mest signifikante biten, i stedet for å kopiere sign bit, er den ideell for usignerte binære tall, mens den aritmetiske høyreforskyvningen er ideell for signerte to komplement binære tall.
Circular shiftEdit
en annen form for shift er circular shift, bitvis rotasjon eller bitrotasjon.
Rotasjonrediger
venstre sirkulær skift eller roter
|
høyre sirkulær skift eller roter
|
i denne operasjonen, noen ganger kalt rotate no carry, blir bitene «rotert» som om venstre og høyre ende av registret ble slått sammen. Verdien som flyttes til høyre under et venstreskift, er hvilken verdi som ble skiftet ut til venstre, og omvendt for en høyreskiftoperasjon. Dette er nyttig hvis det er nødvendig å beholde alle eksisterende biter, og brukes ofte i digital kryptografi.
Roter gjennom carryEdit
venstre rotere gjennom bære
|
høyre rotere gjennom bære
|
Rotate through carry Er en variant av rotasjonsoperasjonen, hvor biten som forskyves inn (i hver ende) er den gamle verdien av bæreflagget, og biten som forskyves ut (i den andre enden) blir den nye verdien av bæreflagget.
en enkelt rotere gjennom bære kan simulere en logisk eller aritmetisk skift av en posisjon ved å sette opp bære flagget på forhånd. Hvis for eksempel bæreflagget inneholder 0, er x RIGHT-ROTATE-THROUGH-CARRY-BY-ONE
et logisk høyreforskyvning, og hvis bæreflagget inneholder en kopi av tegnbiten, er x RIGHT-ROTATE-THROUGH-CARRY-BY-ONE
et aritmetisk høyreforskyvning. Av denne grunn har noen mikrokontrollere som low end PICs bare rotere og rotere gjennom bære, og ikke bry deg med aritmetiske eller logiske skiftinstruksjoner.
Roter gjennom bære er spesielt nyttig når du utfører skift på tall som er større enn prosessorens opprinnelige ordstørrelse, fordi hvis et stort antall er lagret i to registre, må biten som skiftes av den ene enden av det første registeret komme inn i den andre enden av det andre. Med rotate-through-carry, er den biten «lagret» i bæreflagget under det første skiftet, klar til å skifte inn under det andre skiftet uten ekstra forberedelse.
på høynivåspråkrediger
C-familyEdit
i C-familiens språk er de logiske skiftoperatørene «<<
«for venstre skift og» >>
» for høyre skift. Antall steder å skifte er gitt som det andre argumentet til operatøren. For eksempel,
x = y << 2;
tilordner x
resultatet av å skifte y
til venstre med to biter, som tilsvarer en multiplikasjon med fire.
Skift kan resultere i implementeringsdefinert oppførsel eller udefinert oppførsel, så vær forsiktig når du bruker dem. Resultatet av å skifte med en bit teller større enn eller lik ordets størrelse er udefinert oppførsel I C og C++. Høyre-skiftende en negativ verdi er implementeringsdefinert og anbefales ikke av god kodingspraksis; resultatet av venstre-skiftende en signert verdi er udefinert hvis resultatet ikke kan representeres i resultattypen.
i C# er høyre skift et aritmetisk skift når den første operanden er en int eller lang. Hvis den første operanden er av typen uint eller ulong, er høyre skift et logisk skifte.
Sirkulære skifterrediger
C-familien av språk mangler en rotasjonsoperatør, men en kan syntetiseres fra skiftoperatørene. Det må tas hensyn til at uttalelsen er godt utformet for å unngå udefinert oppførsel og tidsangrep i programvare med sikkerhetskrav. For eksempel er en naiv implementering som venstre roterer en 32-biters usignert verdi x
av n
posisjoner ganske enkelt:
uint32_t x = ..., n = ...;uint32_t y = (x << n) | (x >> (32 - n));
et skift med 0
biter resulterer imidlertid i udefinert virkemåte i høyreuttrykket (x >> (32 - n))
fordi 32 - 0
er 32
og 32
er utenfor området inkludert. Et nytt forsøk kan resultere i:
uint32_t x = ..., n = ...;uint32_t y = n ? (x << n) | (x >> (32 - n)) : x;
hvor skiftbeløpet er testet for å sikre at det ikke introduserer udefinert oppførsel. Grenen legger imidlertid til en ekstra kodebane og presenterer en mulighet for timinganalyse og angrep, noe som ofte ikke er akseptabelt i programvare med høy integritet. I tillegg kompilerer koden til flere maskininstruksjoner, som ofte er mindre effektive enn prosessorens innfødte instruksjon.
for å unngå udefinert oppførsel og grener under GCC og Clang, anbefales følgende. Mønsteret er anerkjent av mange kompilatorer, og kompilatoren vil avgi en enkelt rotasjonsinstruksjon:
uint32_t x = ..., n = ...;uint32_t y = (x << n) | (x >> (-n & 31));
det er også kompilatorspesifikke intrinsics som implementerer sirkulære skift, som _rotl8, _rotl16, _rotr8, _rotr16 I Microsoft Visual C++. Clang gir noen rotere intrinsics For Microsoft kompatibilitet som lider problemene ovenfor. GCC tilbyr ikke rotere intrinsics. Intel gir også x86 Intrinsics.
JavaEdit
I Java er alle heltallstyper signert, så operatorene «<<
» og «>>
» utfører aritmetiske skift. Java legger til operatøren «>>>
» for å utføre logiske høyre skift, men siden de logiske og aritmetiske venstreskiftoperasjonene er identiske for signert heltall, er det ingen «<<<
» operatør I Java.
Flere detaljer Om Java shift operatører:
- operatorene
<<
(venstre skift),>>
(signert høyre skift) og>>>
(usignert høyre skift) kalles skiftoperatørene. - typen av skiftuttrykk er den forfremmede typen av venstre operand. For eksempel
aByte >>> 2
tilsvarer((int) aByte) >>> 2
. - hvis den forfremmede typen av venstre operand er int, brukes bare de fem laveste ordensbitene til høyre operand som skiftavstand. Det er som om høyre operand ble utsatt for en bitvis logisk og operatør & med maskeverdien 0x1f (0b11111). Skiftavstanden som faktisk brukes, er derfor alltid i området 0 til 31, inkludert.
- hvis den forfremmede typen av venstre operand er lang, brukes bare de seks laveste ordensbitene til høyre operand som skiftavstand. Det er som om høyre operand ble utsatt for en bitvis logisk og operatør & med maskeverdien 0x3f (0b111111). Skiftavstanden som faktisk brukes, er derfor alltid i området 0 til 63, inkludert.
- verdien av
n > > > s
er n høyreforskyvede s-bitposisjoner med nullutvidelse. - i bit-og skiftoperasjoner konverteres typen
byte
implisitt tilint
. Hvis byte-verdien er negativ, er den høyeste biten en, så brukes de til å fylle opp de ekstra bytene i int. Såbyte b1 = -5; int i = b1 / 0x0200;
vil resultere ii == -5
.
JavaScriptEdit
JavaScript bruker bitvis operasjoner for å evaluere hver av to eller flere enheter sted til 1 eller 0.
PascalEdit
I Pascal, så vel som i alle dens dialekter (Som Object Pascal og Standard Pascal), er de logiske venstre-og høyre skiftoperatørene henholdsvis «shl
» og «shr
«. Selv for signerte heltall, shr
oppfører seg som et logisk skift, og kopierer ikke tegnbiten. Antall steder å skifte er gitt som det andre argumentet. For eksempel tilordner følgende x resultatet av å skifte y til venstre med to biter:
x := y shl 2;