The "elegant" algorithm or the ugly assembly language?
For the assembler:
" is "Logical Shift Left." The bits of the register (__tmp_reg__) are shifted "upward" one place, and the most significant bit is shifted into the "carry" status flag, which you can sort of think of as a temporary 1-bit register.
So if you had 10100000
to start with, after the first shift you have 1 in the Carry bit, and 01000000
in the register.
" is "rotate right through carry", which does exactly the reverse: the register (%[out]) is shifted right/downward, and the old value of the carry bit moves into the most significant bit of the register.
If THAT register had xyzxyzzz
(random bits that we don't care about, really, because they'll all dissappear), after the first ror, it will contain 1xyzxyzz
(the carry gets the bit that's shifted out, z, as well, but we don't care about that either, because the next lsl will overwrite it.)
So we're pushing the bits leftward out of our original register and rightward into a new register. After we've done this twice, the source register will have 10000000
and the destination 01xyzxyz
. After the third time we have 00000000
. After 8 repetitions, we'll have 00000000
, which is the reversed bit pattern that we wanted.
The somewhat odd formats of the register names (%[in]
) and other bits of weird syntax (": [out] "=r" (result) : [in] "r" (x)
") are FEATURES provided by the C compiler to permit assembler to co-exist and mix (and even optimize) with C/C++ code. They're best handled by having a big screen and calling up a relevant tutorial in another window; they certainly don't make the code particularly readable if you're only familiar with the syntax that Atmel defines and documents. "\n\t
" is supposed to aid formatting in listings (newline, tab.) The whole thing would look a lot clearer in "pure" assembler, something like:
bitrev: ;;; Accept a byte in R24, reverse the bits and return the result in R24 as well.
;;; Uses R0 as a temporary register.
mov R0, R24 ;copy our input value into R0
lsl R0 ;shift input left into carry
ror R24 ;rotate carry right into output
ror R24 ; (4 bits done)
ror R24 ; (8 bits done. Finished!)
ret ; return with our result in R24 (R0 trashed)