Bitvis operation

bitskiftningarna betraktas ibland som bitvisa operationer, eftersom de behandlar ett värde som en serie bitar snarare än som en numerisk kvantitet. I dessa operationer flyttas eller flyttas siffrorna åt vänster eller höger. Register i en datorprocessor har en fast bredd, så vissa bitar kommer att ”flyttas ut” från registret i ena änden, medan samma antal bitar ”flyttas in” från den andra änden; skillnaderna mellan bitskiftoperatörer ligger i hur de bestämmer värdena för de förskjutna bitarna.

Bit addressingEdit

om bredden på registret (ofta 32 eller till och med 64) är större än antalet bitar (vanligtvis 8) av den minsta adresserbara enheten (atomelement), ofta kallad byte, inducerar skiftoperationerna ett adresseringsschema på bitarna.Bortsett från gränseffekterna i båda ändarna av registret uppträder aritmetiska och logiska skiftoperationer på samma sätt, och ett skift med 8 bitpositioner transporterar bitmönstret med 1 byte-position på följande sätt:

  • Little-endian beställning:
ett vänsterskifte med 8 positioner ökar byteadressen med 1
  • Little-endian beställning:
ett högerskifte med 8 positioner minskar byteadressen med 1
  • stor-endian beställning:
ett vänsterskifte med 8 positioner minskar byteadressen med 1
  • stor-endian beställning:
ett högerskifte med 8 positioner ökar byteadressen med 1

aritmetiska shiftEdit

Huvudartikel: aritmetiska shift
vänster aritmetiska Skift

höger aritmetiska Skift

i ett aritmetiskt Skift kasseras bitarna som förskjuts ur vardera änden. I ett vänster aritmetiskt Skift flyttas nollor in till höger; i en höger aritmetisk förskjutning flyttas teckenbiten (MSB i två komplement) till vänster och bevarar därmed operandens tecken.

detta exempel använder ett 8-bitars register, tolkat som två komplement:

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

i det första fallet flyttades den vänstra siffran förbi slutet av registret och en ny 0 flyttades till den högra positionen. I det andra fallet flyttades den högra 1 ut (kanske in i bärflaggan) och en Ny 1 kopierades till den vänstra positionen och behöll tecknet på numret. Flera skift förkortas ibland till ett enda SKIFT med ett visst antal siffror. Till exempel:

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

ett vänster aritmetiskt SKIFT med n motsvarar att multiplicera med 2n (förutsatt att värdet inte överflödar), medan ett höger aritmetiskt SKIFT med n av ett tvås komplementvärde motsvarar att dividera med 2n och avrunda mot negativ oändlighet. Om det binära talet behandlas som ett komplement, resulterar samma högerskiftoperation i division med 2n och avrundning mot noll.

logisk skiftedit

Huvudartikel: Logisk förändring
vänster logisk Skift

rätt logiskt Skift

i ett logiskt Skift flyttas nollor in för att ersätta de kasserade bitarna. Därför är de logiska och aritmetiska vänsterskiftningarna exakt desamma.

men eftersom den logiska högerförskjutningen sätter in värdet 0 bitar i den mest signifikanta biten, istället för att kopiera teckenbiten, är den idealisk för osignerade binära tal, medan den aritmetiska högerförskjutningen är idealisk för signerade två komplementbinära tal.

cirkulär shiftEdit

ytterligare information: cirkulär shift

en annan form av skift är cirkulär shift, bitvis rotation eller bit rotation.

Roteraredigera

vänster cirkulär skift eller rotera

höger cirkulär skift eller rotera

i denna operation, ibland kallad rotate no carry, ”roteras” bitarna som om de vänstra och högra ändarna av registret förenades. Värdet som flyttas till höger under en vänsterskift är vilket värde som skiftades ut till vänster och vice versa för en högerskiftningsoperation. Detta är användbart om det är nödvändigt att behålla alla befintliga bitar och används ofta i digital kryptografi.

rotera genom carryEdit

vänster rotera genom bär

höger rotera genom bär

rotera genom bär är en variant av rotate-operationen, där biten som flyttas in (i vardera änden) är det gamla värdet på bärflaggan, och biten som flyttas ut (i andra änden) blir det nya värdet på bärflaggan.

en enda rotation genom bärning kan simulera en logisk eller aritmetisk förskjutning av en position genom att ställa in bärflaggan i förväg. Till exempel, om bärflaggan innehåller 0, är x RIGHT-ROTATE-THROUGH-CARRY-BY-ONE ett logiskt högerskifte, och om bärflaggan innehåller en kopia av teckenbiten, är x RIGHT-ROTATE-THROUGH-CARRY-BY-ONE ett aritmetiskt högerskifte. Av denna anledning har vissa mikrokontroller som low end PICs bara rotera och rotera genom carry, och stör inte med aritmetiska eller logiska skiftinstruktioner.

rotera genom bärning är särskilt användbart när du utför skift på tal som är större än processorns ursprungliga ordstorlek, för om ett stort antal lagras i två register måste biten som flyttas från ena änden av det första registret komma in i den andra änden av den andra. Med rotate-through-carry ”sparas” den biten i bärflaggan under det första skiftet, redo att växla in under det andra skiftet utan extra förberedelse.

på högnivåspråkedit

mer information: Circular shift 2708>

C-familyEdit

på C-family språk är de logiska skiftoperatörerna ”<<” för left shift och ”>>” för right shift. Antalet platser att flytta anges som det andra argumentet till operatören. Till exempel,

x = y << 2;

tilldelar x resultatet av att flytta y till vänster med två bitar, vilket motsvarar en multiplikation med fyra.

skift kan resultera i implementeringsdefinierat beteende eller odefinierat beteende, så man måste vara försiktig när man använder dem. Resultatet av att skifta med en biträkning större än eller lika med ordets storlek är odefinierat beteende i C och C++. Högerförskjutning av ett negativt värde är implementeringsdefinierat och rekommenderas inte av god kodningssed; resultatet av vänsterförskjutning av ett signerat värde är odefinierat om resultatet inte kan representeras i resultattypen.

i C# är högerskiftet ett aritmetiskt skift när den första operanden är en int eller lång. Om den första operanden är av typen uint eller ulong är högerskiftet ett logiskt Skift.

cirkulär shiftsEdit

C-familjen av språk saknar en rotera operatör, men man kan syntetiseras från skiftoperatörerna. Försiktighet måste vidtas för att säkerställa att uttalandet är välformat för att undvika odefinierat beteende och tidsattacker i programvara med säkerhetskrav. Till exempel, en naiv implementering som lämnade roterar ett 32-bitars osignerat värde x med n positioner är helt enkelt:

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

en förskjutning med 0 bitar resulterar emellertid i odefinierat beteende i högra uttrycket (x >> (32 - n)) eftersom 32 - 0 är 32 och 32 ligger utanför intervallet inklusive. Ett andra försök kan resultera i:

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

där skiftbeloppet testas för att säkerställa att det inte introducerar odefinierat beteende. Filialen lägger dock till en ytterligare kodväg och presenterar en möjlighet för tidsanalys och attack, vilket ofta inte är acceptabelt i programvara med hög integritet. Dessutom sammanställs koden till flera maskininstruktioner, vilket ofta är mindre effektivt än processorns ursprungliga instruktion.

för att undvika det odefinierade beteendet och grenarna under GCC och Clang rekommenderas följande. Mönstret känns igen av många kompilatorer, och kompilatorn kommer att avge en enda rotationsinstruktion:

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

det finns också kompilatorspecifika inneboende som implementerar cirkulära skift, som _rotl8, _rotl16, _rotr8, _rotr16 i Microsoft Visual C++. Clang ger vissa rotera inneboende för Microsoft-kompatibilitet som lider av problemen ovan. GCC erbjuder inte rotera inneboende. Intel tillhandahåller också x86 inneboende.

JavaEdit

i Java är alla heltalstyper signerade, så operatörerna ”<<” och ”>>” utför aritmetiska Skift. Java lägger till operatorn ” >>> ”för att utföra logiska högerskift, men eftersom de logiska och aritmetiska vänsterskiftoperationerna är identiska för signerat heltal finns det ingen” <<< ” -operator i Java.

mer information om Java shift-operatörer:

  • operatörerna << (vänster shift), >> (signerad höger shift) och >>> (osignerad höger shift) kallas skiftoperatörerna.
  • typen av skiftuttryck är den främjade typen av den vänstra operanden. Till exempel är aByte >>> 2 ekvivalent med ((int) aByte) >>> 2.
  • om den främjade typen av vänster operand är int, används endast de fem lägsta ordningsbitarna i höger operand som skiftavstånd. Det är som om den högra operanden utsattes för en bitvis logisk och operatör & med maskvärdet 0x1f (0b11111). Skiftavståndet som faktiskt används är därför alltid i intervallet 0 till 31 inklusive.
  • om den främjade typen av vänsteroperand är lång, används endast de sex lägsta ordningsbitarna i högeroperand som skiftavstånd. Det är som om den högra operanden utsattes för en bitvis logisk och operatör & med maskvärdet 0x3f (0b111111). Skiftavståndet som faktiskt används är därför alltid i intervallet 0 till 63 inklusive.
  • värdet på n >>> s är N högerförskjutna s-bitpositioner med nollförlängning.
  • i bit-och skiftoperationer konverteras typen byte implicit till int. Om bytevärdet är negativt är den högsta biten en, då används de för att fylla i extra byte i int. Så byte b1 = -5; int i = b1 / 0x0200; kommer att resultera i i == -5.

Javascript

JavaScript använder bitvisa operationer för att utvärdera var och en av två eller flera enheter plats till 1 eller 0.

PascalEdit

i Pascal, liksom i alla dess dialekter (som Object Pascal och Standard Pascal), är de logiska vänster-och högerskiftoperatörerna ”shl” respektive ”shr”. Även för signerade heltal beter sig shr som ett logiskt skift och kopierar inte teckenbiten. Antalet platser att flytta anges som det andra argumentet. Till exempel tilldelar följande x resultatet av att flytta y till vänster med två bitar:

x := y shl 2;

Lämna ett svar

Din e-postadress kommer inte publiceras.

More: