7. Méta-programmation et macro-programmation

Contenu de cette section

La programmation en assembleur est casse-pieds, sauf pour des parties sensibles de programmes. Vous devrier utiliser les outils appropriés en fonction des outils que vous souhaitez créer. Donc ne choisissez pas l'assembleur lorsque cela ne correspond pas. C, OCAML, perl, Scheme, peuvent être un meilleur choix pour vos programmes.

Toutefois, il existe certains cas où ces outils ne donnent pas un contrôle assez fin sur votre machine, et l'assembleur est alors utile, voir nécessaire. Dans ces cas, vous allez apprécier un système de macro-programmation et de méta-programmation qui vous permet de ne définir qu'une seul fois des symboles que vous répettez et ainsi pouvoir les utiliser bon nombre de fois grâce à un système d'expansion. Cela permet une programmation plus sûre, de modifier le code plus simplement, etc. Un pur assembleur n'est généralement pas suffisant, même lorsque vous ne faîtes que de petites routines que vous utilisez dans des programmes C.

7.1 Qu'est-ce que cela veut dire ?

gcc

gcc permet (et demande) à ce que vous spécifiez des contraintes sur les registres dans votre code en ligne, de telle manière que l'optimiseur le sache. Donc, l'assembleur en ligne est vraiment fait de modèles, et pas forcément de code au sens du terme.

Ensuite, vous pouvez transformer votre code en macros CPP, de telle manière que n'importe qui puisse s'en servir comme fonction en ligne ou macro C. Les fonctions en lignes ressembles de très près aux macros, mais elles sont parfois plus propres à utiliser. Faites attention car dans un tel cas, le code sera dupliqué, donc seules des étiquettes locales (comme 1:) devraient être définies dans le code assembleur. Toutefois, une macro-commande pourrait autoriser le passage d'une étiquette non définie en local en paramètre. Notez également que certaines erreurs de votre code ou de gcc peuvent apparaître lorsque vous utilisez des fonctions en ligne en assembleur si les contraintes de registres n'ont pas été déclarées proprement.

Enfin, le langage C peut être considéré comme étant une bonne abstraction au langage assembleur, ce qui vous évite une bonne partie des problèmes de l'assembleur.

Prenez garde à certaines optimisations qui peuvent passer des arguments à des fonctions via des registres. Dans ce cas, ces fonctions pourraient ne plus être joignables de l'assembleur d'une manière standard, à moins que vous n'utilisiez le mot clef asmlinkage. Consultez les sources du noyau Linux pour plus d'exemples.

gas

gas ne possède absolument aucune capacité de gestion de macros. Toutefois, gcc fait passer les fichiers .S via cpp avant d'être donné à gas. Les fichiers .s ne sont générés qu'une seule fois et passés directement à gas. Encore une fois, consultez les sources de Linux.

gasp

Ce programme correspond au préprocesseur de macro commandes en assembleur de GAS. Consultez sa documentation en texinfo.

as86

Il gère quelques macros assez simple, mais je n'ai pas réussi à trouver de la documentation. Maintenant, les sources sont très parlants, donc si vous êtes intéressé, vous devriez les comprendre très facilement. Si vous avez besoin de plus que le stricte minimum, vous devriez utiliser un filtre externe (voir un peu plus bas...)

Autres assembleurs

7.2 Filtres externes

Quelque soit la gestion de macro supportée par votre assembleur, ou quelque soit le langage que vous utilisez (même C !), si le langage n'est pas assez puissant pour vous, vous pouvez passer les fichiers à travers un filtre externe en incluant une règle dans le Makefile, comme par exemple :

%.s:    %.S autre_dependances
        $(FILTRE) $(OPTIONS_FILTRE) < $< > $@

cpp

cpp n'est pas vraiment très expressif mais il est assez bon pour des opérations simples. Il est standard et appelé d'une manière transparente par gcc.

Comme exemple de limitation, vous ne pouvez pas déclarer d'objets de telle manière que les destructeurs soient automatiquement appelés à la fin du bloc de déclaration. Vous ne pouvez pas déclarer les données et le code qui va les manipuler, etc.

cpp est livré avec le compilateur C. gcc (voir ci-dessus) est un compilateur C libre, qui le contient.

m4

m4 vous donne toute la puissante du traitement de macro instructions, avec un langage équivalent à celui de Turing, la récursivité, les expressions régulières, etc. Vous pouvez faire tout ce que vous ne pouviez pas faire avec cpp.

Récupérez macro4th/This4th à partir de ftp://ftp.forth.org/pub/Forth/ dans Reviewed/ ANS/ (?). Des exemples de programmation avancée sont disponibles dans les sources de Tunes 0.0.0.25.

Toutefois, il y a pas mal de problèmes de sémantiques avec les quotes qui vous obligent à utiliser des continuation explicites, des macros récursives si vous souhaitez faire de la programmation avancée (ce qui n'est pas sans rappeler -- d'ailleurs, est-ce que quelqu'un a déjà essayé d'utiliser TeX comme un macroprocesseur pour autre chose que du traitement de texte ?). Ce n'est pas pire que cpp car il n'autorise pas les quotes et la récursivité.

La bonne version de m4 a récupérer est la version GNU m4 1.4 (ou plus récente si elle existe), qui possède le plus de caractéristiques et le moins de bugs et de limitations.

Macro-traitements avec vos propres filtres

Vous pouvez écrire vos propres filtres d'expansion de macros avec les outils habituels : perl, awk, sed, etc. C'est rapide à faire, et vous contrôlez tout. Mais bien sûr, toute la puissante des traitement dépend de vous.

Macro-programmation

Au lieu d'utiliser un filtre externe qui expanse les macro-commandes, une manière de travailler consiste a écrire des programmes qui écrivent des parties ou tous les autres programmes.

Par exemple, vous pourriez utiliser un programme qui génère le code source pour générer les tables correspondantes aux opérations sinus et cosinus, pour extraire une représentation code source d'un binaire, pour compiler vos images en routines d'affichage rapide, pour extraire de la documentation, du code d'initialisation et de terminaison, des tables de descriptions. Cela pourrait être un code source généré à partir de scripts perl, shell, scheme qui effectue le traitement (particulièrement utile lorsque certains types de données doivent être dupliqués dans bon nombre de tables de références croisées et dans du code).

Pensez-y !


Chapitre suivant, Chapitre Précédent

Table des matières de ce chapitre, Table des matières générale

Début du document, Début de ce chapitre