Binary shifts and bit manipulation
Shifting bits around
- Moving all the bits left or right is a shift — and it's a fast way to multiply or divide.
- Setting individual bits lets one byte hold up to 8 on/off flags.
- These tricks are everywhere in low-level and embedded code.
Logical shifts
- A logical shift moves all bits left or right, filling the new positions with 0.
- Left shift by 1 (
LSL #1) — for an unsigned number this is × 2. - Right shift by 1 (
LSR #1) — this is integer ÷ 2. - Shifting by $n$ places multiplies or divides by $2^n$. Example:
00001011(11)LSL #1→00010110(22).
The 8-bit value 00001011 (11) is shifted left by 1 (LSL #1). What is the new denary value?
A left shift by 1 multiplies by 2: $11 \times 2 = 22$ (00010110).
Shifting an unsigned number left by 3 places multiplies it by what number?
Shifting by $n$ places multiplies by $2^n$, so by 3 places is $2^3 = 8$.
Arithmetic right shift
- A plain logical right shift puts a 0 in the top bit — which would make a negative signed number look positive.
- An arithmetic right shift keeps (copies) the sign bit, so a negative number stays negative.
- Use it to divide a signed number by powers of 2.
An arithmetic right shift differs from a logical right shift because it:
It preserves the sign bit, so dividing a negative signed number by a power of 2 keeps it negative.
Bit manipulation with masks
- Embedded devices often use one bit of a register per signal. Using a mask:
- Set bit $n$:
R = R OR mask(mask has bit $n$ = 1). - Clear bit $n$:
R = R AND mask(mask has bit $n$ = 0, the rest 1). - Toggle bit $n$:
R = R XOR mask(mask has bit $n$ = 1). - Test bit $n$:
R AND mask, then check if the result is non-zero.
To SET a particular bit to 1, you combine the register with a mask using:
OR with a mask that has that bit = 1 forces the bit to 1 and leaves the others unchanged.
To TOGGLE a bit (flip 0↔1), you use:
XOR with a 1 flips the bit; XOR with a 0 leaves it unchanged.
To TEST whether a bit is set, you AND the register with a mask and then:
AND with a single-bit mask isolates that bit; a non-zero result means the bit was set.
You've got it
- logical shift fills with 0: left = ×2, right = ÷2; by $n$ places = $\times$ or $\div\ 2^n$
- arithmetic right shift keeps the sign bit (for negative signed numbers)
- masks: OR to set, AND to clear, XOR to toggle, AND + test to read a bit