Previous Next Contents

4. METAPROGRAMMING/MACROPROCESSING

Assembly programming is a bore, but for critical parts of programs. You should use the appropriate tool for the right task, so don't choose assembly when it's not fit; C, OCAML, perl, Scheme, might be a better choice for most of your programming. However, there are cases when these tools do not give a fine enough control on the machine, and assembly is useful or needed. In those case, you'll appreciate a system of macroprocessing and metaprogramming that'll allow recurring patterns to be defined once, and reused multiple times, by automatically inline expansion, which allows safer programming, easier modification, etc. A ``plain'' assembler is often not enough, even when one is doing only small routines to link with C.

4.1 What's integrated into the above

GCC

GCC allows (and requires) you to specify register constraints in your ``inline assembly'' code, so the optimizer always know about it; thus, inline assembly code is really made of patterns, not forcibly exact code.

Then, you can make put your assembly into CPP macros, so anyone can use it in as any C function/macro. and inline C functions Inline functions resemble macros very much, but are sometimes cleaner to use. Beware that in those cases, code will be duplicated, so only local labels (of 1: style) should be defined in that asm code. However, a macro would allow the name for a non local defined label to be passed. Also, note that some bug in your code or in GCC may appear when inlining functions with asm code where the register constraints weren't declared properly and/or confuse GCC.

Lastly, the C language itself may be considered as a good abstraction to assembly programming, which relieves you from most of the trouble of assembling.

Beware that some optimizations that involve passing arguments to functions through registers may make those functions unsuitable to be called from assembly in the standard way, least you give them the attribute asmlinkage. See the linux kernel sources for examples.

GAS

GAS has absolutely NO macro capability included. However, GCC and passes .S files through CPP before to feed them to GAS. Files whose name ends in .s are the generated ones, and are passed directly to GAS. Again and again, see Linux sources for examples.

GASP

It adds all the usual macroassembly tricks to GAS. See its texinfo docs.

NASM

Some limited macro support (already?). If you have some bright idea, you might wanna contact the authors, as they are actively developing it. Meanwhile, see about external filters below.

AS86

It has some simple macro support, but I couldn't find docs. Now the sources are very straightforward, so if you're interested, you should understand them easily. If you need more than the basics, you should use an external filter (see below in section 3.2)

OTHER ASSEMBLERS

Win32FORTH: CODE and END-CODE are macros that do not switch from interpretation mode, so you have access to the full power of FORTH words, immediate or not, while assembling.

TUNES: it doesn't work yet, but the Scheme language is a real high-level language that allows arbitrary meta-programming.

4.2 External Filters

Whatever is the macro support from your assembler, or whatever language you use (even C !), if the language is not expressive enough to you, you can have files passed through an external filter with a Makefile rule like that:


%.s:    %.S other_dependencies
        $(FILTER) $(FILTER_OPTIONS) < $< > $@

CPP

CPP is truely not very expressive, but it's enough for easy things, it's standard, and called transparently by GCC.

As an example of its limitations, you can't declare objects so that destructors are automatically called at the end of the declaring block, you can't co-declared data and the code to process it, etc.

CPP came with your C compiler. If you could make it without one, don't bother fetching any (though I wonder how you could). GCC (see above) is a free C compiler you could have fetched.

M4

M4 gives you the full power of macroprocessing, with a Turing equivalent language, recursion, regular expressions, etc. You can do with it everything that CPP cannot.

See macro4th/This4th from ftp://ftp.forth.org/pub/Forth/ in Reviewed/ ANS/ (?), or the Tunes 0.0.0.25 sources as examples of advanced macroprogramming using m4.

However, its fucked up quoting semantics force you to use explicit continuation-passing tail-recursive macro style if you want to do advanced macro programming (which is remindful of TeX -- BTW, has anyone tried to use TeX as a macroprocessor for anything else than typesetting ?). This is NOT worse than CPP that does not allow quoting and recursion anyway.

The right version of m4 to get is GNU m4 1.4 (or later if exists), which has the most features and the least bugs or limitations of all.

Macroprocessing with yer own filter

You can write your own simple macro-expansion filter with the usual tools: perl, awk, sed, etc. That's quick to do, and you control everything. But of course, any power in macroprocessing must be earned the hard way.

Metaprogramming

Instead of using an external filter that expands macros, one way to do things is to write programs that write part or all of other programs.

For instance, you could use a program outputing source code to generate sine/cosine/whatever lookup tables, to extract a source-form representation of a binary file, to compile your bitmaps into fast display routines, to extract documentation, initialization/finalization code, description tables, as well as normal code from the same source files, to have customized assembly code, generated from a perl/shell/scheme script that does arbitrary processing, (particularly useful when some kind of data must be mirrored at into many cross-referencing tables and code chunks). etc.

Think about it !

Backends from existing compilers

Compilers like SML/NJ, Objective CAML, MIT-Scheme, etc, do have their own generic assembler backend, which you might or not want to use, if you intend to generate code semi-automatically from the according languages.

The New-Jersey Machine-Code Toolkit

There is a project, using the programming language Icon, to build a basis for producing assembly-manipulating code. See around http://www.cs.virginia.edu/~nr/toolkit/

Tunes

The Tunes OS project is developping its own assembler as an extension to the Scheme language, as part of its development process. It doesn't run at all yet, though help is welcome.

The assembler manipulates symbolic syntax trees, so it could equally serve as the basis for a assembly syntax translator, a disassembler, a common assembler/compiler back-end, etc. Also, the full power of a real language, Scheme, make it unchallenged as for macroprocessing/metaprograming.

http://www.eleves.ens.fr:8080/home/rideau/Tunes/


Previous Next Contents