bitové posuny jsou někdy považovány za bitové operace, protože oni léčit hodnotu jako řada bitů, spíše než jako numerické množství. V těchto operacích jsou číslice posunuty nebo posunuty doleva nebo doprava. Registry v procesoru počítače mají pevnou šířku, takže se některé kousky budou „přesunula“ z rejstříku na jednom konci, zatímco stejný počet bitů, které jsou „posunul“ z druhého konce; rozdíly mezi bitové operátory posunutí leží v tom, jak určit hodnoty posunuté-v bitů.
Trochu addressingEdit
Pokud se šířka rejstříku (často 32 nebo dokonce 64) je větší než počet bitů (obvykle 8), nejmenší adresovatelná jednotka (prvek s atomovým), často nazýván byte, posun operace vyvolat adresovací schéma na kousky.Bez ohledu na okrajové efekty na obou koncích registru, aritmetické a logické řazení operací chovat stejné a posun o 8 bitů pozice transporty bit vzor 1 bajt na pozici následujícím způsobem:
|
vlevo posun o 8 pozic zvyšuje byte adresu 1 |
|
a právě posun o 8 pozic snižuje byte adresu 1 |
|
vlevo posun o 8 pozic snižuje byte adresu 1 |
|
a právě posun o 8 pozic zvyšuje byte adresu 1 |
Aritmetický shiftEdit
V aritmetické směny, bity jsou posunuty z jednoho konce jsou vyřazeny. V levém aritmetickém posunu jsou nuly posunuty vpravo; v pravém aritmetickém posunu je znaménkový bit (MSB v doplňku dvou) posunut vlevo, čímž se zachová znaménko operandu.
Tento příklad používá 8-bitový registr, interpretován jako dvojkový doplněk:
00010111 (decimal +23) LEFT-SHIFT= 00101110 (decimal +46)
10010111 (decimal −105) RIGHT-SHIFT= 11001011 (decimal −53)
V prvním případě, vlevo číslice byla posunuta minulosti konci rejstříku, a nový 0 byla posunuta do polohy zcela vpravo. V druhém případě, že nejpravější 1 se posunula ven (možná do carry flag), a nová 1 byl zkopírován do polohy zcela vlevo, zachování znaménko čísla. Vícenásobné posuny jsou někdy zkráceny na jeden posun o určitý počet číslic. Například:
00010111 (decimal +23) LEFT-SHIFT-BY-TWO= 01011100 (decimal +92)
levé aritmetický posun o n se rovná se vynásobí 2 n (za předpokladu, že hodnota není přetečení), zatímco právo aritmetický posun o n o dvojkový doplněk hodnota je ekvivalentní dělení 2n a zaokrouhlení směrem k minus nekonečnu. Pokud je binární číslo považováno za doplněk, pak stejná operace pravého posunu vede k rozdělení o 2n a zaokrouhlení směrem k nule.
logický posuneditovat
Vlevo logický posun
|
Správné logické řazení
|
V logickém řazení, nuly jsou posunuté nahradit vyřazené kousky. Proto jsou logické a aritmetické posuny doleva přesně stejné.
Nicméně, jak logické vpravo-posun vloží hodnota 0 bitů do nejvíce významný bit, místo kopírování znaménkový bit, je ideální pro nepodepsaný binární čísla, zatímco aritmetický právo-shift je ideální pro podepsána dvojkový doplněk binární čísla.
Kruhové shiftEdit
Další forma směny je kruhový posun, bitové rotace, nebo trochu rotace.
RotateEdit
Vlevo kruhový posun nebo otočení
|
pravý kruhový posun nebo otočení
|
V této operaci, někdy tzv. otočit ne nést, jsou bity „otáčet“, jako by na levé a pravé koncích rejstříku byly spojeny. Hodnota, která je posunuta doprava během levého posunu, je jakákoli hodnota, která byla posunuta doleva, a naopak pro operaci pravého posunu. To je užitečné, pokud je nutné zachovat všechny existující bity a často se používá v digitální kryptografii.
Otáčet přes carryEdit
Levá rotace skrze carry
|
Doprava a otočte přes carry
|
Otáčet přes nést je varianta otočit provozu, kde bit je posunut v (na obou koncích) je stará hodnota carry flag, a bit je posunut z (na druhém konci) se stává novou hodnotu nesou vlajky.
jediné otočení přes carry může simulovat logický nebo aritmetický posun o jednu pozici nastavením příznaku carry předem. Pokud například příznak carry obsahuje 0, pak x RIGHT-ROTATE-THROUGH-CARRY-BY-ONE
je logický posun doprava a pokud příznak carry obsahuje kopii znakového bitu, pak x RIGHT-ROTATE-THROUGH-CARRY-BY-ONE
je aritmetický posun doprava. Z tohoto důvodu, některé mikroprocesory, jako jsou low-end Fotky jen otočit a otáčet přes sebe a neobtěžuj s aritmetické nebo logické řazení podle pokynů.
Otočit prostřednictvím přenášení je užitečné zejména při provádění směn na čísla větší než procesor nativní slovo velikost, protože pokud velké množství, je uložena ve dvou registrech, bit, která se přesouvá z jednoho konce první rejstříku, musí přijít na druhém konci druhém. S rotate-through-carry, tento bit je „uložen“ ve vlajce carry během první směny, připraven k posunu během druhé směny bez jakékoli další přípravy.
v jazycích vysoké úrovněeditovat
C-familyEdit
V C-rodina jazyků, logické operátory posunutí jsou „<<
“ pro levý shift a „>>
“ pro pravý shift. Počet míst k posunu je uveden jako druhý argument operátorovi. Například,
x = y << 2;
přiřadí x
výsledek posunu y
doleva o dva bity, což odpovídá násobení čtyřmi.
posuny mohou mít za následek chování definované implementací nebo nedefinované chování, proto je třeba při jejich používání věnovat pozornost. Výsledkem posunu o počet bitů větší nebo roven velikosti slova je nedefinované chování v C A C++. Vpravo-posun negativní hodnota je provádění definovány a nedoporučuje dobré kódování praxe; výsledkem doleva-posun podepsané hodnota je undefined, pokud výsledek nelze reprezentovat v typ výsledku.
v C# je pravý posun aritmetický posun, když první operand je int nebo dlouhý. Pokud je první operand typu uint nebo ulong, pravý posun je logický posun.
Circular shiftsEdit
rodina jazyků C postrádá operátor rotace, ale jeden může být syntetizován z operátorů řazení. Je třeba dbát na to, aby prohlášení bylo dobře vytvořeno, aby se zabránilo nedefinovaným útokům na chování a načasování v softwaru s bezpečnostními požadavky. Například naivní implementace, která vlevo otočí 32bitovou nepodepsanou hodnotu x
o n
pozice, je jednoduše:
uint32_t x = ..., n = ...;uint32_t y = (x << n) | (x >> (32 - n));
Nicméně, posun od 0
bity výsledky v nedefinované chování v pravé ruce výrazu (x >> (32 - n))
protože 32 - 0
32
, a 32
je mimo rozsah inclusive. Druhý pokus může vyústit v:
uint32_t x = ..., n = ...;uint32_t y = n ? (x << n) | (x >> (32 - n)) : x;
kde posun výše je testován pro zajištění nezavádí nedefinované chování. Větev však přidává další cestu kódu a představuje příležitost pro analýzu časování a útok, což je často nepřijatelné v softwaru s vysokou integritou. Kromě toho se kód kompiluje do více strojových instrukcí, což je často méně efektivní než nativní instrukce procesoru.
Chcete-li se vyhnout nedefinovanému chování a větvím pod GCC a Clang, doporučujeme následující. Vzor je rozpoznán mnoho kompilátory, a kompilátor bude vydávat single rotate instrukce:
uint32_t x = ..., n = ...;uint32_t y = (x << n) | (x >> (-n & 31));
Tam jsou také kompilátor specifické intrinsics provádění cyklické posuny, jako _rotl8, _rotl16, _rotr8, _rotr16 v aplikaci Microsoft Visual C++. Clang poskytuje některé rotující vnitřnosti pro kompatibilitu společnosti Microsoft, která trpí výše uvedenými problémy. GCC nenabízí rotate intrinsics. Intel také poskytuje vnitřní prvky x86.
JavaEdit
v Javě jsou podepsány všechny celočíselné typy, takže operátory „<<
“ a „>>
“ provádějí aritmetické posuny. Java přidává operátor „>>>
„k provádění logických pravých posunů, ale protože logické a aritmetické operace levého posunu jsou shodné pro celé číslo se znaménkem, v Javě neexistuje žádný operátor“ <<<
„.
další podrobnosti o operátorech Java shift:
- operátory
<<
(levý shift),>>
(podepsal pravý shift), a>>>
(unsigned pravý shift) se nazývají směny operátorů. - typ výrazu shift je Podporovaný typ levého operandu. Například
aByte >>> 2
odpovídá((int) aByte) >>> 2
. - pokud je povýšený Typ levého operandu int, použije se jako posunová vzdálenost pouze pět bitů pravého operandu nejnižšího řádu. Je to, jako by pravostranný operand byl podroben bitové logice a operátoru & s hodnotou masky 0x1f (0b11111). Skutečně použitá posunová vzdálenost je tedy vždy v rozmezí 0 až 31, včetně.
- je-li Podporovaný typ levého operandu dlouhý, použije se jako posunová vzdálenost pouze šest bitů pravého operandu nejnižšího řádu. Je to, jako by pravý operand byl podroben bitové logice a operátoru & s hodnotou masky 0x3f (0b111111). Skutečně použitá posunová vzdálenost je proto vždy v rozmezí 0 až 63, včetně.
- hodnota
n >>> s
je n právo-posunul s trochu pozic s nulovým rozšíření. - v bitových a shift operacích je typ
byte
implicitně převeden naint
. Pokud je hodnota bajtu záporná, nejvyšší bit je jeden, pak se používají k vyplnění dalších bajtů v int. Takžebyte b1 = -5; int i = b1 | 0x0200;
bude mít za následeki == -5
.
JavaScriptEdit
JavaScript používá bitové operace k vyhodnocení každé ze dvou nebo více jednotek místo 1 nebo 0.
PascalEdit
V Pascalu, stejně jako ve všech jeho dialekty (jako Object Pascal a Standardní Pascal), logické, levý a pravý shift jsou provozovatelé „shl
“ a „shr
„, resp. Dokonce i pro podepsaná celá čísla se shr
chová jako logický posun a nekopíruje znaménkový bit. Počet míst k posunu je uveden jako druhý argument. Například následující přiřadí x výsledek posunutí y doleva o dva bity:
x := y shl 2;