2004-07-21 Joerg Wunsch
* doc/api/faq.dox: Fix the use of progmem tables, closes
savannah bug #9669.
Index: doc/api/faq.dox
===================================================================
RCS file: /cvsroot/avr-libc/avr-libc/doc/api/faq.dox,v
retrieving revision 1.33
diff -u -u -r1.33 faq.dox
--- doc/api/faq.dox 6 Apr 2004 20:09:22 -0000 1.33
+++ doc/api/faq.dox 21 Jul 2004 21:36:10 -0000
@@ -731,7 +731,11 @@
int main (void)
{
char buf[32];
- strcpy_P (buf, array[1]);
+ PGM_P p;
+ int i;
+
+ memcpy_P(&p, &array[i], sizeof(PGM_P));
+ strcpy_P(buf, p);
return 0;
}
\endcode
@@ -740,37 +744,65 @@
in flash as such:
\code
-0000008c :
- 8c: 46 6f ori r20, 0xF6 ; 246
- 8e: 6f 00 .word 0x006f ; ????
-
-00000090 :
- 90: 42 61 ori r20, 0x12 ; 18
- 92: 72 00 .word 0x0072 ; ????
-
-00000094 :
- 94: 8c 00 .word 0x008c ; ????
- 96: 90 00 .word 0x0090 ; ????
-\endcode
-
-\c foo is at addr 0x008c.
-\c bar is at addr 0x0090.
-\c array is at addr 0x0094.
+00000026 :
+ 26: 2e 00 .word 0x002e ; ????
+ 28: 2a 00 .word 0x002a ; ????
-Then in main we see this:
+0000002a :
+ 2a: 42 61 72 00 Bar.
-\code
- strcpy_P (buf, array[1]); /* copy bar into buf */
- de: 60 e9 ldi r22, 0x90 ; 144
- e0: 70 e0 ldi r23, 0x00 ; 0
- e2: ce 01 movw r24, r28
- e4: 01 96 adiw r24, 0x01 ; 1
- e6: 0e 94 79 00 call 0xf2
+0000002e :
+ 2e: 46 6f 6f 00 Foo.
\endcode
-The addr of bar (0x0090) is loaded into the r23:r22 pair which is the second
-parameter passed to strcpy_P. The r25:r24 pair is the addr of buf.
+\c foo is at addr 0x002e.
+\c bar is at addr 0x002a.
+\c array is at addr 0x0026.
+
+Then in main we see this:
+
+\code
+ memcpy_P(&p, &array[i], sizeof(PGM_P));
+ 70: 66 0f add r22, r22
+ 72: 77 1f adc r23, r23
+ 74: 6a 5d subi r22, 0xDA ; 218
+ 76: 7f 4f sbci r23, 0xFF ; 255
+ 78: 42 e0 ldi r20, 0x02 ; 2
+ 7a: 50 e0 ldi r21, 0x00 ; 0
+ 7c: ce 01 movw r24, r28
+ 7e: 81 96 adiw r24, 0x21 ; 33
+ 80: 08 d0 rcall .+16 ; 0x92
+\endcode
+
+This code reads the pointer to the desired string from the ROM table
+\c array into a register pair.
+
+The value of \c i (in r22:r23) is doubled to accomodate for the word
+offset required to access array[], then the address of array (0x26) is
+added, by subtracting the negated address (0xffda). The address of
+variable \c p is computed by adding its offset within the stack frame
+(33) to the Y pointer register, and memcpy_P is
+called.
+\code
+ strcpy_P(buf, p);
+ 82: 69 a1 ldd r22, Y+33 ; 0x21
+ 84: 7a a1 ldd r23, Y+34 ; 0x22
+ 86: ce 01 movw r24, r28
+ 88: 01 96 adiw r24, 0x01 ; 1
+ 8a: 0c d0 rcall .+24 ; 0xa4
+\endcode
+
+This will finally copy the ROM string into the local buffer \c buf.
+
+Variable \c p (located at Y+33) is read, and passed together with the
+address of buf (Y+1) to strcpy_P. This will copy the
+string from ROM to \c buf.
+
+Note that when using a compile-time constant index, omitting the first
+step (reading the pointer from ROM via memcpy_P)
+usually remains unnoticed, since the compiler would then optimize the
+code for accessing \c array at compile-time.
Back to \ref faq_index.