Fun with bits 1

What does the following ARM code do to the value in register r0?

SUB r1,r0,#1

AND r0,r1,r0

Suppose that we are using 8-bit arithmetic and that r0 initially contains the binary
value 11011100. Subtracting 1 gives 11011011 and ANDing with 11011100 gives 1101000.

What’s happened? The 1 in the least-significant bit position has been inverted to
give 0. The effect of this code is to take a word and force the least-significant
bit that is a 1 to to be cleared to; for example 010111000 would become 010110000.

If we’d used a brute force method, we might have done something like:

Count = 1

Repeat

Shift x one place right

count = count + 1

Until carry out = 1 or count = 32

Repeat

Shift x one place left

count = count - 1

Until count = 0

Why does the algorithm work?

We are evaluating X(X - 1)

Consider X as the bit pattern xxxx100…0. This is equivalent to xxxx000…0 + 0000100…0.
If we subtract 1 from this we get: xxxx000…0 + 0000011…1 = xxxx011…0.

If we now perform a logical AND between xxxx100…0 and xxxx011…1 we get xxxx000…0,
which is the original value with the least-significant 1 cleared.