There is nothing wrong in the solution; your disassembler (avr-objdump -d
, part of binutils
package) is buggy.
See page 97 of the Atmel AVR instruction set manual (PDF). The lpm
instruction variants are encoded as
1001 0101 1100 1000 = 0x95C8 lpm r0,Z
1001 000? ???? 0100 = 0x9??4 lpm r?,Z
1001 000? ???? 0101 = 0x9??5 lpm r?,Z+
Assuming we trust the Atmel documentation better than your disassembler, then
84 91 lpm r24,Z
whereas
85 91 lpm r24,Z+
Indeed, avr-gcc (GCC) 4.8.2 compiles the inline assembly to the same two bytes (84 91
) using avr-gcc-4.8.2 -O2 -fomit-frame-pointer -mmcu=avr25
, and lists it as lpm r24,Z
in the assembly source file (using -S
option); when compiled to an object file, and disassembling with avr-objdump (GNU binutils) 2.23.1 using avr-objdump -d
, the instruction is still 84 91
lpm r24,Z
.
This makes me believe it is a bug in avr-objdump (part of GNU binutils). Ah yes, reported here, and apparently fixed in binutils-2.23.1 in October 2013.
In short, only the disassembly is affected; the disassembly incorrectly shows Z+
when it should show Z
. It does not affect the generated code, only the human-readable output is incorrect. To fix, upgrade to binutils version 2.23.1 or later. If you can't, don't worry: you can safely ignore this error, as it only affects the human-readable disassembly.
Questions?