Quantcast
Channel: Active questions tagged gcc - Stack Overflow
Viewing all articles
Browse latest Browse all 21994

How to declare 16-bits pointer to string in GCC C compiler for arm processor

$
0
0

I tried to declare an array of short pointers to strings (16-bits instead of default 32-bits) in GNU GCC C compiler for ARM Cortex-M0 processor to reduce flash consumption. I have about 200 strings in two language, so reducing the size of pointer from 32-bits to 16-bits could save 800 bytes of flash. It should be possible because the flash size is less than 64 kB so the high word (16-bits) of pointers to flash is constans and equal to 0x0800:

const unsigned char str1[] ="First string";const unsigned char str2[] ="Second string";const unsigned short ptrs[] = {&str1, &str2};    //this line generate error

but i got error in 3-th line

"error: initializer element is not computable at load time"

Then i tried:

const unsigned short ptr1 = (&str1 & 0xFFFF);

and i got:"error: invalid operands to binary & (have 'const unsigned char (*)[11]' and 'int')"

After many attempts i ended up in assembly:

  .section .rodata.strings  .align 2ptr0:ptr3:   .short (str3-str0)ptr4:   .short (str4-str0)str0:str3:   .asciz  "3-th string"str4:   .asciz  "4-th string"

compilation pass well, but now i have problem trying to reference pointers: ptr4 and ptr0 from C code. Trying to pass "ptr4-ptr0" as an 8-bit argument to C function:

ptr = getStringFromTable (ptr4-ptr0)

declared as:

const unsigned char* getStringFromTable (unsigned char stringIndex)

i got wrong code like this:

ldr     r3, [pc, #28]   ; (0x8000a78 <main+164>)ldrb    r1, [r3, #0]ldr     r3, [pc, #28]   ; (0x8000a7c <main+168>)ldrb    r3, [r3, #0]subs    r1, r1, r3uxtb    r1, r1bl      0x8000692 <getStringFromTable>

instead of something like this:

movs    r0, #2bl      0x8000692 <getStringFromTable>

I would be grateful for any suggestion.

.....after a few days.....

Following @TonyK and @old_timer advices i finally solved the problem in the following way:in assembly i wrote:

  .global str0,  ptr0  .section .rodata.strings  .align 2ptr0:   .short (str3-str0)        .short (str4-str0)str0:str3:   .asciz  "3-th string"str4:   .asciz  "4-th string"

then i declared in C:

extern unsigned short ptr0[];extern const unsigned char str0[] ;enum ptrs {ptr3, ptr4};        //automatically: ptr3=0, ptr4=1const unsigned char* getStringFromTable (enum ptrs index)  {  return &str0[ptr0[index]] ;  }

and now this text:

ptr = getStringFromTable (ptr4)

is compiled to the correct code:

08000988: 0x00000120   movs    r0, #10800098a: 0xfff745ff   bl      0x8000818 <getStringFromTable>

i just have to remember to keep the order of enum ptrs each time i will add a string to the assembly and a new item to enum ptrs


Viewing all articles
Browse latest Browse all 21994

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>