Convert RGB integer value into RGB values
AVR ABI, 0

Quantities larger than the registers in the AVR's registers are represented with multiple registers. So, when passing in a 32-bit 'n' to a function, it is passed as 4x8-bit registers. Effectively R(r24),G(r23), and B(r22) are directly addressable without any additional work by virtue of the CPU's register addressing.

Here's some 'C' code for the unpacking operation:

unsigned char r( unsigned long n ){return n&gt;&gt;16&amp;255;}
unsigned char g( unsigned long n ){return n&gt;&gt;8&amp;255;}
unsigned char b( unsigned long n ){return n&gt;&gt;0&amp;255;}


disassembled examples from avr-gcc 4.8:

.global r
.type   r, @function
r:
ret
.size   r, .-r

.global g
.type   g, @function
g:
mov r24,r23
ret
.size   g, .-g

.global b
.type   b, @function
b:
mov r24,r22
ret
.size   b, .-b


For red, GCC just emits the return code since the red byte just happens to be in the return register already. For green and blue it copies the corresponding register into the return register and returns. The actual packing/unpacking is handled by the ABI - when done somewhere other than a function call boundary, it's handled purely by the register addressing. Both the copies and return opcode are overhead required to view this happening in the CPU - the compiler can use these registers directly if not required to place the result in the return register. Free RGB packing/unpacking is available when handing any 32-bit integer.

Another way to think about it is that the AVR's registers represent large numbers as a list of 8-bit registers, and that list happens to unpack RGB for us.