const __flash char str[] = "bla";
static void puts_m (const __flash char *str) {
while (*str) {
usart_putchar (*str);
str++;
}
}
puts_m(str);
--------------------------------------------------------
generates:
--------------------------------------------------------
14a: c6 e2 ldi r28, 0x26 ; 38
14c: d0 e0 ldi r29, 0x00 ; 0
14e: 01 c0 rjmp .+2 ; 0x152 <main+0x4e>
const __flash char str[] = "bla";
static void puts_m (const __flash char *str) {
while (*str) {
usart_putchar (*str);
150: 84 df rcall .-248 ; 0x5a <usart_putchar>
152: fe 01 movw r30, r28
154: 21 96 adiw r28, 0x01 ; 1
156: 85 91 lpm r24, Z+
158: 81 11 cpse r24, r1
15a: fa cf rjmp .-12 ; 0x150 <main+0x4c>
-----------------------------------------------------------
Why is it moving the Y (r29:r28) pointer into Z (r31:r30) ptr and then
incrementing the former when the LPM instructions features
autoincrement itself? More elegant, smaller and faster code would be:
ldi r30, 0x26
ldi r31, 0x00 --- load immediate
rjmp puts
loop: rcall usart_putchar
puts: lpm r24, Z+ --- load program memory
cpse r24, r1 --- compare, skip if equal
rjmp loop
--------------------------------------------------------------------
The above code is compiled with
gcc -mmcu=attiny2313 -g -ggdb -Os -Wall -Wno-main -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums
-ffunction-sections -fdata-sections
-ffreestanding -Wno-unused-function -std=gnu99
avr/main.c
INLINE ASM:
const __flash char str[] = "bla";
static void puts_m (const __flash char *str) {
asm volatile ("\n\t" : : "z" (str)); // we need the location in the Z ptr
14a: e6 e2 ldi r30, 0x26 ; 38
14c: f0 e0 ldi r31, 0x00 ; 0
14e: 01 c0 rjmp .+2 ; 0x152 <main+0x4e>
register u8 temp; // temp. register
goto puts_f;
puts_loop: usart_putchar(temp);
150: 84 df rcall .-248 ; 0x5a <usart_putchar>
puts_f: asm volatile ("lpm %0, Z+ \n\t" : "=r" (temp) );
152: 85 91 lpm r24, Z+
asm volatile ("cpse %0, __zero_reg__\n\t" : : "r" (temp));
154: 81 11 cpse r24, r1
asm volatile goto ("rjmp %l[puts_loop]\n\t" : : :: puts_loop);
156: fc cf rjmp .-8 ; 0x150 <main+0x4c>