3

I'm trying to implement a macro ("MY_MACRO"), which stores a string preceded by a 32 bit integer number in a certain section ("my_section"). Example: MY_MACRO(200, "my first string %u %x");

Here are the options I tried and the problems I'm facing with. I would appreciate any help. (gcc 4.7.3. MIPS cpu)

Option A:

#define MY_MACRO(_num, _string)\
asm volatile(".pushsection .my_section");\
asm volatile(".byte %0, %1, %2, %3" : : "i"((_num >> 24) & 0xFF), "i"((_num >> 16) & 0xFF), "i"((_num >> 8) & 0xFF), "i"(_num & 0xFF)); /* Store the number */ \
asm volatile(".ascii " #_string);\
asm volatile(".popsection");

Compile error (it doesn't occur for each usage of the macro):

c:\Temp\ccpDEDnt.s: Assembler messages:
c:\Temp\ccpDEDnt.s:1024: Warning: .popsection without corresponding .pushsection; ignored

I think the reason is a compiler optimization which changes the instructions order (although each asm instruction is volatile, the compiler is allowed to change the order). Q: Is there any way to disable the compiler optimizations just for the scope of these lines without #pragma? This issue led me to find a solution in which the four asm instructions are unified.


Option B:

#define MY_MACRO(_num, _string)\
asm volatile(".pushsection .my_section\n\t" \
             ".byte %0, %1, %2, %3\n\t" \
             ".ascii " #_string "\n\t" \
             ".popsection" \
             : : "i"((_num >> 24) & 0xFF), "i"((_num >> 16) & 0xFF), "i"((_num >> 8) & 0xFF), "i"(_num & 0xFF));

Compiler errors:

foo.c:733:13: error: invalid 'asm': operand number missing after %-letter
foo.c:733:13: error: invalid 'asm': operand number out of range

Since the string includes the percent sign (%), the compiler interprets it as an asm operands.


Option C:

#define MY_MACRO(_num, _string)\
asm volatile(".pushsection .my_section\n\t" \
             ".byte %0, %1, %2, %3\n\t" \
             ".ascii %4\n\t" \
             ".popsection" \
             : : "i"((_num >> 24) & 0xFF), "i"((_num >> 16) & 0xFF), "i"((_num >> 8) & 0xFF), "i"(_num & 0xFF), "X"(#_string));

Here I tried to pass the string as an operand. I don't even know if it's feasible. I didn't manage to compile this code.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
yhlove
  • 61
  • 2
  • 3

1 Answers1

0

Option B is the right way, however you will need to double all percent signs (%) occurring in your string because that's interpreted as an operand placeholder in the inline asm.

If you don't particularly care about ordering or inlining, you could also let gcc handle it for you:

struct mystruct
{
    int num;
    char string[0];
};

#define MY_MACRO(_num, _string)\
{ static struct mystruct entry __attribute__ ((section (".my_section"))) = { _num, _string }; }
Jester
  • 56,577
  • 4
  • 81
  • 125
  • I cannot double all percent signs because the code is compiled to many platforms. Some of them need to get the string in the regular format. I tried the gcc solution you suggested and got this compile error: "error: initializer-string for array of chars is too long" – yhlove Jun 24 '13 at 06:59
  • That's just a warning, because of the zero-length array, but it should work fine (it does for me). You can disable and reenable that warning in the macro. – Jester Jun 24 '13 at 10:46