Search code examples
gccassemblyc-preprocessorgnu-assembler

Gnu AS doesn't seem to preprocess #defines, but GCC does


I have a potentially large number of constants which are used by an increasing number of source files. I need to be able to play around with its value, so it's convenient for it to be defined in one place.

An example of my situation as follows:

The header file where I define the variables, rmode_loc.h:

#define __ASSEMBLER__

#define BSEQ_HI 0xF000
#define BSEQ_LO 0x0000

An excerpt from some code where they (should) be used, myprog.S:

.code16

/* Include constants */
#include "rmode_loc.h"

_start:

    ...

    push    $BSEQ_HI

    ...

    mov $BSEQ_LO, %bx

However, upon attempting compilation the linker reports the following errors:

myprog.o: In function `_start':
(.text+0x1b): undefined reference to `BSEQ_HI'
myprog.o: In function `_start':
(.text+0x1f): undefined reference to `BSEQ_LO'

Evidently an attempt is being made to link against these 'symbols' - thus I conclude that the preprocessor did not replace the symbols to values as those indicated by rmode_loc.h.

I read on another SO post (can't find the link) where it was mentioned that if the extension of the source file was .s no preprocessing would occur, and the suggestion to define __ASSEMBLER__ was also given - However, this does not seem to be the issue here as all the sources have .S extensions and I added a #define __ASSEMBLY__ in the header.

However, when using GCC as the frontend for compilation, namely gcc myprog.S -o myprog, the BSEQ labels are correctly replaced, and everything compiles.

My question is, what difference in preprocessing is there when using as rather than gcc to yield these results, and are there any significant technical differences when using gcc to compile assembly code instead of as?


Solution

  • GNU as by itself never processes #define directives.

    A special feature of the gcc command is that when given a filename ending in .S, it runs the C preprocessor cpp on it (which processes #define and #include and so forth), and then runs as on the resulting output. But when given a filename ending in .s, it just runs as.

    If you want to use C preprocessor directives, you can either name your files .S and use the gcc command, or name them whatever you want and manually do both passes:

    cpp foo.s |as -o foo.o -