Ce qu'un assembleur trois passes fait qu'un deux passes ne peut pas
Les assembleurs traduisent langage assemblage en code machine. La plupart sont deux passes. Un assembleur trois passes ajoute une troisième traversée pour débloquer capacités que deux passes ne gèrent pas proprement — surtout pour chargement absolu, relocation, et résolution symboles complexes.
Rappel rapide : Flux deux passes
- Passe 1 : Construit table symboles (étiquettes → adresses), calcule tailles instructions, détecte étiquettes dupliquées.
- Passe 2 : Résout symboles, génère code objet, gère références avant via table symboles complétée.
Sortie : Fichier objet relogeable (nécessite linker/loader).
Ce qu'apporte la troisième passe
1. Génération module chargement absolu
La troisième passe attribue adresses mémoire finales, absolues, à chaque instruction et donnée. Sortie = binaire charge-et-lance — pas de linker, pas d'étape relocation. Le chargeur copie juste à l'adresse spécifiée et saute au point entrée. Critique pour :
- Systèmes embarqués cartes mémoire fixes
- Bootloaders, firmware, images ROM
- Environnements enseignement (exécution instantanée)
2. Résolution symboles complète vers adresses absolues
Passe 2 résout symboles vers offsets relatifs (pour relocation). Passe 3 les résout vers adresses finales. Chaque référence externe, référence avant, expression complexe obtient valeur concrète. Permet :
- Symboles debug riches (mappage adresse ↔ étiquette)
- Outils analyse statique
- Listings références croisées
3. Code relogeable avec métadonnées complètes
Assembleurs trois passes peuvent émettre code objet relogeable et modules absolus. Troisième passe construit tables relocation (quelles adresses fixer au chargement) tout en produisant version absolue. Flexibilité pour les deux workflows.
4. Gestion table symboles optimisée
Passe 1 : Collecte. Passe 2 : Résout. Passe 3 : Optimise — tables hachage, hachage parfait, élimination symboles morts, partitionnement par portée. Assemblage plus rapide gros projets (noyaux OS, blobs firmware).
5. Diagnostics erreurs supérieurs
Avec trois phases distinctes, erreurs capturées en contexte :
- Passe 1 : Syntaxe, étiquettes dupliquées, symboles indéfinis (refs avant notées)
- Passe 2 : Incompatibilité opérandes, erreurs plage, débordement relocation
- Passe 3 : Conflits adresses, détection chevauchement, violations bornes absolues
Résultat : ligne/colonne précise + message actionnable, pas « erreur passe 2 ».
Quand vous en utiliseriez un vraiment
- Embarqué bare-metal (pas OS, carte mémoire fixe)
- Assembleurs enseignement (feedback immédiat)
- Rétro-informatique (cibles 8/16-bit, toolchains simples)
- Recherche sécurité (génération shellcode, contrôle adresses exact)
Contexte moderne
La plupart toolchains production (GAS, LLVM-MC, NASM) sont deux passes + linker. Le linker fait ce que passe 3 ferait : assignation adresses finales, traitement relocation, dead stripping. Assembleurs trois passes survivent dans niches où surcoût linker indésirable ou impossible.
En résumé
Assembleurs trois passes échangent complexité pour sortie absolue auto-contenue, diagnostics riches, flexibilité relocation. Ils ne sont pas « meilleurs » — ils sont spécialisés. Si vous écrivez bootloader microcontrôleur avec adresse chargement fixe 0x08000000, assembleur trois passes vous économise script linker. Pour presque tout le reste, deux passes + linker est standard.
