7

My toolchain is a recent version of arm-gcc.

I have a piece of code in an assembly file which must be conditionally included/assembled.

.ifdef MACRO_FROM_CMDLINE
 Assembly instr1
 Assembly instr2
.endif

Encapsulated code is a recent addition.

I have tried both:

gcc -x assembler-with-cpp --defsym MACRO_FROM_CMDLINE=1 <along with other necessary options> 

gcc -x assembler-with-cpp -D MACRO_FROM_CMDLINE=1 <along with other necessary options>   

The -D results in "Invalid identifier for .ifdef " and ".endif without .if" errors.

The --defsym results in "MACRO_FROM_CMDLINE=1 : No such file or directory", "unrecognized option --defsym" errors.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Raj
  • 857
  • 11
  • 26

2 Answers2

14

The gcc binary drives the compilation process by invoking a number of other programs in sequence to actually perform the various stages of work (compiling, assembling, linking).

When you say:

gcc -x assembler-with-cpp -D MACRO_FROM_CMDLINE=1 ...

you are asking it to run the source through the C preprocessor, and then run the result through the assembler.

The C preprocessor step will turn:

.ifdef MACRO_FROM_CMDLINE

into:

.ifdef 1

before passing it to the assembler, which then can't make sense of it. This is why you get the "invalid identifier" error. It also explains why using C preprocessor #ifdef fixes the problem.


--defsym doesn't work because it's an option to the assembler, not the gcc driver program. (The gcc driver does understand and pass through some options to some of the programs it invokes, but not all.)

You can, however, pass arbitrary options through to the assembler using the

-Wa,option[,option...]

syntax, which tells the gcc driver to pass those option(s) through to the assembler (as a list of space-separated options).

For example:

gcc -x assembler-with-cpp -Wa,--defsym,MACRO_FROM_CMDLINE=1 ...

adds

--defsym MACRO_FROM_CMDLINE=1

to the list of options passed to as when gcc invokes it, and that's how to make your original .ifdef example work.


You can see the individual programs invoked by gcc, and the options it actually passes to them, by adding the -v option.

In this case, you should see something called cc1 (the actual GCC C compiler binary) invoked with the -E flag (preprocess only) to preprocess the input to a temporary file, and then as invoked on the temporary file to assemble it.

Matthew Slattery
  • 45,290
  • 8
  • 103
  • 119
1

Strange, but it it turns out I needed to use the C syntax in the assembly file.

#ifdef MACRO
  Assembly Instruction
  Assembly Instruction
#endif

And the macro had to be passed using the -D option.

Raj
  • 857
  • 11
  • 26
  • GAS supports both afaik, Why don't you call GAS directly instead of going through gcc on your assembly files ? – sgupta Oct 07 '12 at 17:31
  • Using gcc (and not GNU as directly) has the benefit of invoking the linker after compilation whereas using as directly you need to take the additional step of linking afterwards, using ld. Sooo... just a 10 second time saver? – adam May 17 '17 at 17:20
  • @sgupta: Using CPP is the best choice here, and `as` directly *doesn't* preprocess. (But `#` is the comment character for x86, so the file might still assemble!) Using `as` directly is bad advice. Name your file `foo.S` and build it with `gcc` + whatever gcc options, e.g. `-m32`, `-c`. – Peter Cordes Dec 14 '17 at 06:20