This may seem convoluted but it may also achieve the same goal. You could create a C macro that simply creates #defines
for strings and values that may need to propagate to an assembler header. You can create a function that uses these macros to generate the defines. You can then use -S
feature of GCC to output the assembly and then use GREP to sift out the defines that were generated dumping them to an include file that can be used by your assembly (.S) file.
File gnuasm.h
:
#define GNUASM_DEFINE_STR(SYMBOL, STR) \
__asm__ ("#define " SYMBOL " " #STR);
#define GNUASM_DEFINE_VAL(SYMBOL, VALUE) \
__asm__ ("#define " SYMBOL " %a0" :: "n"(VALUE));
The trick in the macro is to use the asm directive to emit the defines. This will cause them to appear in the generated .s
file. GNUASM_DEFINE_STR
can be used at global scope but for GNUASM_DEFINE_VAL
to work you'll need to put it in a dummy function.
Your common.h
would remain unchanged:
struct someStruct {
int data;
};
#define SOME_STRUCT_SIZE sizeof(struct someStruct)
#define SOME_MAGIC 0x12345678
Create a dummy C file (it doesn't need to be linked with your project) that includes common.h
and the gnuasm.h
macros file with a dummy function. In this case I'll call it common-defs.c
:
#include "gnuasm.h"
#include "common.h"
/* Dummy function used to generate the defines we need */
void common_defines(void)
{
GNUASM_DEFINE_STR("SOME_STRING", "some string");
GNUASM_DEFINE_VAL("SOME_STRUCT_SIZE", SOME_STRUCT_SIZE);
GNUASM_DEFINE_VAL("SOME_MAGIC", SOME_MAGIC);
return;
}
This file is meant to be compiled and for the assembly output to be generated like this:
gcc common-defs.c -c -S
This produces a file common-defs.s
. This is the assembly code that represents the C code. All the defines we emitted can then be parsed out with GREP and then output into an include file that our assembly file can include:
grep "#define" common-defs.s >common.inc
Now in our asm.S
file you can include this at the top:
#include "common.inc"
The generated common.inc
file would appear something like:
#define SOME_STRING "some string"
#define SOME_STRUCT_SIZE 4
#define SOME_MAGIC 305419896
When using struct
another useful thing for assembly are the offsets of member variables. Those could be generated like this:
GNUASM_DEFINE_VAL("SOME_STRUCT_DATA_OFFSET", offsetof(struct someStruct, data));