C headers in Asm

18 Jun 2012

NOTE (2016-11-01)

Since people are apparently still finding this page four years later (yay! Cool URLs don't change!): I've since found a better and more correct way of doing this.

If you're compiling using gcc, you can just name your assembly files (with includes and macros and stuff) whatever.S (capital S), and compile them right down to whatever.o as you normally would (using gcc, not as).

GNU make also has a builtin rule that does this automatically... yeah...

From this I've learned the following

  • Trust make. It's terribly powerful if you trust it to be.
  • GCC is not the GNU C Compiler. It's the GNU Compiler Collection.

Something that always annoyed me is how hard it is to synchronize constants between assembly and c code. In assembler, you define a constant value as

EXACT_PI equ 3

and in c

#define EXACT_PI 3

As is usually the case with things that annoy me, there is of course a solution to this, as I found out today. The solution is the c preprocessor.

Normally, when you run a c compiler, it makes multiple passes over your source file. The first one or two times, it runs a pre-processor. The preprocessor checks for things like #include and #define and replaces macros. The next pass actually compiles the code. Then the compiler invokes a linker and so on.

What I found out today is that you can run only the preprocessor and it will replace all the preprocessor code and ignore the rest. In other words, you can use c preprocessor macros in assembler. Awesome!

So, how is this done? Well, here's a minimal (non-working) example:


#include <header.h>

mov eax, EXACT_PI


#pragma once

#define EXACT_PI 3

#ifndef __ASSEMBLER__
// This is not evaluated if header.h is included from an assembly file.

This is compiled through:

$ cpp -I include -x assembler-with-cpp myAsmFile.asm -o myAsmFile.s
$ nasm myAsmFile.s

The -x-flag tells the preprocessor what type of file the following input files are. assembler-with-cpp means cpp will ignore everything but the preprocessor commands.

An alternative to cpp is gcc -E. Actually, this is often exactly the same thing...

This is implemented in git commit 742f2348ec.


comments powered by Disqus
© 2012 Thomas Lovén - @thomasloven - GitHub