Multiply, divide and modulus
Multiplying in binary is shifting and adding. Shifting left multiplies by 2, shifting right divides by 2, and the remainder of a division by a power of two is just the low bits. General division is the expensive one.
Multiplying is shift and add
Each 1 bit in the multiplier adds a shifted copy of the multiplicand. For 5 × 3, the multiplier 011 has two 1s: 101 (5) plus 101 shifted left once, 1010 (10), is 1111, which is 15. Hardware multipliers do this in parallel; the idea is the same.
Powers of two are free
Shifting left by one doubles a value, since every bit moves up one place: 0011 (3) becomes 0110 (6), and two shifts make 1100 (12). Shifting right halves it, dropping the lowest bit. Compilers turn a multiply or divide by a constant power of two into a shift for you, but writing the shift makes the intent clear in register code.
Division and modulus
Dividing by 4 is a shift right by 2, and the remainder is the two bits that were shifted out. With x = 13 (1101): x >> 2 is 11 (3) and x & 3 is 01 (1), so 13 = 4 × 3 + 1. In general, for a power of two N, x % N equals x & (N - 1), which is how a ring buffer wraps its index without a division.
uint8_t x = 13;
uint8_t q = x >> 2; // 3
uint8_t r = x & 3; // 1, same as x % 4
These tricks hold for unsigned values. Right-shifting a negative signed value is implementation-defined in C, so use unsigned types for bit work.
Division by anything else
Dividing by a value that is not a power of two needs a divider. Cortex-M3 and above have a hardware divide instruction; Cortex-M0 and M0+ do not, so a division is a call into a software routine that takes many more cycles. Check your core's reference manual, and in a fast loop prefer a shift, a mask or a precomputed reciprocal.