Assembly HOWTO Francois-Rene Rideau rideau@ens.fr v0.4l, 16 Novembre 1997 (Version francaise realisee par Eric Dumas dumas@freenix.fr dumas@Linux.EU.Org, et Fare Rideau rideau@ens.fr, 11 Novembre 1997). Ce document decrit comment programmer en assembleur x86 en n'utilisant que des outils de developpement _l_i_b_r_e_s, et tout particulierement avec le systeme d'exploitation Linux sur la plate-forme i386. Les informa- tions contenues dans ce document peuvent etre applicables ou non applicables a d'autres plates-formes materielles ou logicielles. Les contributions a ce documents seront acceptees avec gratitude. _m_o_t_s_- _c_l_e_f_s: assembleur, libre, macroprocesseur, preprocesseur, asm, inline asm, 32 bits, x86, i386, gas, as86, nasm 11.. IInnttrroodduuccttiioonn 11..11.. CCooppyyrriigghhtt Copyright (c) 1996,1997 Francois-Rene Rideau. Ce document peut etre redistribue sous les termes de la license LDP, disponibles a . 11..22.. NNoottee iimmppoorrttaannttee Ceci est cense etre la derniere version que j'ecrirai de ce document. Il y a un candidat pour reprendre en charge le document, mais jusqu'a ce qu'il le reprenne completement en main, je serai heureux de m'occuper de tout courrier concernant ce document. Vous etes tout specialement invites a poser des questions, a y repondre, a corriger les donnees, a ajouter de nouvelles informations, a completer les references sur d'autres logiciels, a mettre en evidence les erreurs et lacunes du document. Si vous etes motives, vous pouvez meme pprreennddrree eenn cchhaarrggee ccee ddooccuummeenntt. En un mot, apporter votre contribution! Pour contribuer a ce document, contactez la personne qui apparait actuellement en charge. Au moment ou j'ecris ces lignes, il s'agit de Francois-Rene Rideau ) ainsi que de Paul Anderson . 11..33.. AAvvaanntt--PPrrooppooss Ce document est destine a repondre aux questions les plus frequemment posees par les gens qui developpent ou qui souhaitent developper des programmes en assembleurs x86 32 bits en utilisant des logiciels _l_i_b_r_e_s, et tout particulierement sous Linux. Vous y trouverez egalement des liens sur d'autres documents traitant d'assembleur, fondes sur des outils logiciels qui ne sont pas libres, pas 32-bit, ou pas dedies a l'architecture x86, bien que cela ne soit pas le but principal de ce document. Etant donne que l'interet principal de la programmation en assembleur est d'etablir les fondations de systemes d'exploitation, d'interpreteurs, de compilateurs, et de jeux, la ou un compilateur C n'arrive plus a fournir le pouvoir d'expression necessaire (les performances etant de plus en plus rarement un probleme), nous insisteront sur le developpement de tels logiciels. 11..33..11.. CCoommmmeenntt uuttiilliisseerr ccee ddooccuummeenntt Ce document contient des reponses a un certain nombre de questions frequemment posees. Des URL y sont donnes, qui pointent sur des sites contenant documents ou logiciels. Prenez conscience que les plus utiles de ces sites sont dupliques sur des serveurs miroirs, et qu'en utilisant le site miroir le plus proche de chez vous, vous evitez a un gachis inutile aussi bien de precieuses ressources reseau communes a l'Internet que de votre propre temps. Ainsi, il existe un certain nombre de gros serveurs dissemines sur la planete, qui effectuent la duplication d'autres sites importants. Cherchez ou se trouvent ces sites et identifiez les plus proches de chez vous (du point de vue du reseau). Parfois, la liste des miroirs est donnees dans un fichier ou dans le message de connexion. Suivez ces conseils. Si ces informations ne sont pas presentes, utilisez le programme archie. La version la plus recente de ce document peut etre trouvee sur ou mais les repertoires de HowTo Linux _d_e_v_r_a_i_e_n_t normalement etre a peu pres a jour (je ne peux pas le garentir): (?) La version francaise de ce document peut etre trouvee sur le site 11..33..22.. AAuuttrreess ddooccuummeennttss ddee rreeffeerreennccee +o si vous ne savez ce qu'est le _l_i_b_r_e logiciel, lisez avec attention la GPL (GNU General Public License), qui est utilisee dans un grand nombre de logiciels libres, et est une source d'inspiration pour la plupart des autres licences d'utilisations de logiciels libres. Elle se trouve generalement dans un fichier nomme COPYING, avec une version pour les bibliotheques de routines dans un fichier nomme COPYING.LIB. Les ecrits publies par la FSF (free software foundation) peuvent egalement vous aider a comprendre le phenomene. +o plus precisement, les logiciels libres interessants sont ceux desquels les sources sont disponibles, que l'on peut consulter, corriger, et desquels on peut emprunter une partie. Lisez les licences d'utilisation avec attention et conformez-vous y. +o il existe une FAQ dans le forum de discussion comp.lang.asm.x86 qui repond aux questions generales concernant la programmation en assembleur pour x86, et aux questions concernant certains assembleurs commerciaux dans un environnement DOS 16 bits. Certaines de ces reponses peuvent s'appliquer a la programmation 32 bits, aussi serez-vous sans-doute interesses de lire cette FAQ... +o Sont disponibles des FAQs, de la documentation, et des sources, concernant la programmation sur votre plate-forme preferee, quelqu'elle soit, et vous devriez les consulter pour les problemes lies a votre plate-forme qui ne seraient pas specifique a la programmation en assembleur. 11..44.. HHiissttoorriiqquuee ddee ddooccuummeenntt Chaque version inclue quelques modifications et corrections mineures, qui ne sont pas indiquees a chaque fois. VVeerrssiioonn 00..11 2233 AAvvrriill 11999966 Francois-Rene "Fare" Rideau cree et diffuse initialement le document sous forme d'un mini-HOWTO car ``Je suis un peu fatigue d'avoir a repondre encore et toujours aux memes questions dans le forum comp.lang.asm.x86'' VVeerrssiioonn 00..22 44 MMaaii 11999966 * VVeerrssiioonn 00..33cc 1155 JJuuiinn 11999966 * VVeerrssiioonn 00..33ff 1177 OOccttoobbrree 11999966 Tim Potter indique l'option -fasm pour activer l'assembleur en- ligne de GCC sans le reste des optimisations de -O. VVeerrssiioonn 00..33gg 22 NNoovveemmbbrree 11999966 Creation de l'historique. Ajout de pointeurs dans la section sur la compilation croisee. Ajout d'une section concernant la programmation des entrees/sorties sous Linux (en particulier pour l'acces video). VVeerrssiioonn 00..33hh 66 NNoovveemmbbrree 11999966 plus sur la compilation croisee - voir sur sunsite: devel/msdos/ VVeerrssiioonn 00..33ii 1166 NNoovveemmbbrree 11999966 NASM commence a etre particulierement interessant VVeerrssiioonn 00..33jj 2244 NNoovveemmbbrree 11999966 Reference sur la version francaise VVeerrssiioonn 00..33kk 1199 DDeecceemmbbrree 11999966 Quoi? J'avais oublie de parler de Terse? VVeerrssiioonn 00..33ll 1111 JJaannvviieerr 11999977 * VVeerrssiioonn 00..44pprree11 1133 JJaannvviieerr 11999977 Le mini-HOWTO au format texte est transforme en un authentique HOWTO au format linuxdoc-sgml, pour explorer les possibilites dudit format. VVeerrssiioonn 00..44 2200 JJaannvviieerr 11999977 Premiere diffusion de ce HOWTO. VVeerrssiioonn 00..44aa 2200 JJaannvviieerr 11999977 Ajout de la section CREDITS VVeerrssiioonn 00..44bb 33 FFeevvrriieerr 11999977 NASM mis avant AS86 VVeerrssiioonn 00..44cc 99 FFeevvrriieerr 11999977 Ajout de la partie "Avez-vous besoin d'utilisateur l'assembleur?" VVeerrssiioonn 00..44dd 2288 FFeevvrriieerr 11999977 Annonce fantome d'un nouveau responsable de ce HowTo. VVeerrssiioonn 00..44ee 1133 MMaarr 11999977 Version diffusee pour DrLinux VVeerrssiioonn 00..44ff 2200 MMaarrss 11999977 * VVeerrssiioonn 00..44gg 3300 MMaarrss 11999977 * VVeerrssiioonn 00..44hh 1199 JJuuiinn 11999977 Ajouts a propos de "Comment ne pas utiliser l'assembleur"; mises a jour concernant NASM et GAS. VVeerrssiioonn 00..44ii 1177 JJuuiilllleett 11999977 Informations sur l'acces au mode 16 bits a partir de Linux. VVeerrssiioonn 00..44jj 77 SSeepptteemmbbeerr 11999977 * VVeerrssiioonn 00..44kk 1199 OOccttoobbrree 11999977 je (Fare) reprends en main la traduction francaise du HowTo VVeerrssiioonn 00..44ll 1166 NNoovveemmbbrree 11999977 version pour LSL 6eme edition. Il s'agit encore d'une nouvelle ``toute derniere version realisee par Fare avant qu'un nouveau responsable ne prenne la main''. 11..55.. CCrreeddiittss Je souhaiterais remercier les personnes suivantes: +o Linus Torvalds pour Linux +o Bruce Evans pour bcc d'ou as86 est extrait +o Simon Tatham et Julian Hall pour NASM. +o Jim Neil pour Terse +o Greg Hankins pour la coordination des HOWTOs +o Raymond Moon pour sa FAQ +o Eric Dumas pour la traduction initiale en francais... (l'auteur, francais, est le premier attriste de devoir ecrire l'original en anglais) +o Paul Anderson et Rahim Azizarab pour m'avoir aide, a defaut de reprendre le HowTo en main. +o toutes les personnes qui ont contribue a l'ecriture de ce document, par leurs idees, remarques ou leur soutient moral. 22.. AAvveezz--vvoouuss bbeessooiinn ddee ll''aasssseemmbblleeuurr?? Je ne veux en aucun cas jouer les empecheurs-de-tourner-en-rond, mais voici quelques conseils issus d'une experience gagnee a la dure. 22..11.. LLee PPoouurr eett llee CCoonnttrree 22..11..11.. LLeess aavvaannttaaggeess ddee ll''aasssseemmbblleeuurr L'assembleur peut vous permettre de realiser des operations tres bas niveau: +o vous pouvez acceder aux registres et aux ports d'entrees/sorties specifiques a votre machine; +o vous pouvez parfaitement controler le comportemant du code dans des sections critiques ou pourraient sinon advenir un blocage du processeur ou des peripheriques; +o vous pouvez sortir des conventions de production de code de votre compilateur habituel; ce qui peut vous permettre d'effectuer certaines optimisations (par exemple contourner les regles d'allocation memoire, gerer manuellement le cours de l'execution, etc.); +o acceder a des modes de programmation non courants de votre processeur (par exemple du code 16 bits pour l'amorcage ou l'interfacage avec le BIOS, sur les peces Intel); +o vous pouvez construire des interfaces entre des fragments de codes utilisant des conventions incompatibles (c'est-a-dire produit par des compilateurs differents ou separes par une interface bas- niveau); +o vous pouvez generer un code assez rapide pour les boucles importantes pour pallier aux defauts d'un compilateur qui ne sait les optimiser (mais bon, il existe des compilateurs optimisateurs librement disponibles!); +o vous pouvez generer du code optimise "a la main" qui est plus parfaitement regle pour votre configuration materielle precise, meme s'il ne l'est pour aucune autre configuration; +o vous pouvez ecrire du code pour le compilateur optimisateur de votre nouveau langage. (c'est la une activite a laquelle peu se livrent, et encore, rarement.) 22..11..22.. LLeess iinnccoonnvveenniieennttss ddee ll''aasssseemmbblleeuurr L'assembleur est un langage tres bas niveau (le langage du plus bas niveau qui soit au dessus du codage a la main de motifs d'instructions en binaire). En consequence: +o l'ecriture de code en est longue et ennuyeuse; +o les bogues apparaissent aisement; +o les bogues sont difficiles a reperer et supprimer; +o il est difficile de comprendre et de modifier du code (la maintenance est tres compliquee); +o le resultat est extremement peu portable vers une autre architecture, existante ou future; +o votre code ne sera optimise que une certaine implementation d'une meme architecture: ainsi, parmi les plates-formes compatibles Intel, chaque realisation d'un processeur et de ses variantes (largeur du bus, vitesse et taille relatives des CPU/caches/RAM/Bus/disques, presence ou non d'un coprocesseur arithmetique, et d'extensions MMX ou autres) implique des techniques d'optimisations parfois radicalement differentes. Ainsi different grandement les processeurs deja existant et leurs variations: Intel 386, 486, Pentium, PPro, Pentium II; Cyrix 5x86, 6x86; AMD K5, K6. Et ce n'est surement pas termine: de nouveaux modeles apparaissent continuellement, et cette liste meme sera rapidement depassee, sans parler du code ``optimise'' qui aura ete ecrit pour l'un quelconque des processeurs ci-dessus. +o le code peut egalement ne pas etre portable entre differents systemes d'exploitation sur la meme architecture, par manque d'outils adaptes (GAS semble fonctionner sur toutes les plates- formes; NASM semble fonctionner ou etre facilement adaptable sur toutes les plates-formes compatibles Intel); +o un temps incroyable de programmation sera perdu sur de menus details, plutot que d'etre efficacement utilise pour la conception et le choix des algorithmes utilises, alors que ces derniers sont connus pour etre la source de la majeure partie des gains en vitesse d'un programme. Par exemple, un grand temps peut etre passe a grapiller quelques cycles en ecrivant des routines rapides de manipulation de chaines ou de listes, alors qu'un remplacement de la structure de donnees a un haut niveau, par des arbres equilibres et/ou des tables de hachage permettraient immediatement un grand gain en vitesse, et une parallelisation aisee, de facon portable permettant un entretien facile. +o une petite modification dans la conception algorithmique d'un programme aneantit la validite du code assembleur si patiemment elabore, reduisant les developpeurs au dilemne de sacrifier le fruit de leur labeur, ou de s'enchainer a une conception algorithmique obsolete. +o pour des programmes qui fait des choses non point trop eloignees de ce que font les benchmarks standards, les compilateurs/optimiseurs commerciaux produisent du code plus rapide que le code assembleur ecrit a la main (c'est moins vrai sur les architectures x86 que sur les architectures RISC, et sans doute moins vrai encore pour les compilateurs librement disponible. Toujours est-il que pour du code C typique, GCC est plus qu'honorable). +o Quoi qu'il en soit, ains le dit le saige John Levine, moderateur de comp.compilers, "les compilateurs rendent aisee l'utilisation de structures de donnees complexes; ils ne s'arretent pas, morts d'ennui, a mi-chemin du travail, et produisent du code de qualite tout a fait satisfaisante". Ils permettent egalement de propager _c_o_r_r_e_c_t_e_m_e_n_t les transformations du code a travers l'ensemble du programme, aussi henaurme soit-il, et peuvent optimiser le code par-dela les frontieres entre procedures ou entre modules. 22..11..33.. AAffffiirrmmaattiioonn En pesant le pour et le contre, on peut conclure que si l'assembleur est parfois necessaire, et peut meme etre utile dans certains cas ou il ne l'est pas, il vaut mieux: +o minimiser l'utilisation de code ecrit en assembleur; +o encapsuler ce code dans des interfaces bien definies; +o engendrer automatiquement le code assembleur a partir de motifs ecrits dans un langage plus de haut niveau que l'assembleur (par exemple, des macros contenant de l'assembleur en-ligne, avec GCC); +o utiliser des outils automatiques pour transformer ces programmes en code assembleur; +o faire en sorte que le code soit optimise, si possible; +o utiliser toutes les techniques precedentes a la fois, c'est-a-dire ecrire ou etendre la passe d'optimisation d'un compilateur. Meme dans les cas ou l'assembleur est necessaire (par exemple lors de developpement d'un systeme d'exploitation), ce n'est qu'a petite dose, et sans infirmer les principes ci-dessus. Consultez a ce sujet les sources du noyau de Linux: vous verrez qu'il s'y trouve juste le peu qu'il faut d'assembleur, ce qui permet d'avoir un systeme d'exploitation rapide, fiable, portable et d'entretien facile. Meme un jeu tres celebre comme DOOM a ete en sa plus grande partie ecrit en C, avec une toute petite routine d'affichage en assembleur pour accelerer un peu. 22..22.. CCoommmmeenntt nnee ppaass uuttiilliisseerr ll''aasssseemmbblleeuurr 22..22..11.. MMeetthhooddee ggeenneerraallee ppoouurr oobbtteenniirr dduu ccooddee eeffffiiccaaccee Comme le dit Charles Fiterman dans comp.compilers a propos de la difference entre code ecrit par l'homme ou la machine, ``L'homme devrait toujours gagner, et voici pourquoi: +o Premierement, l'homme ecrit tout dans un langage de haut nivrau. +o Deuxiemement, il mesure les temps d'execution (profiling) pour determiner les endroits ou le programme passe la majeure partie du temps. +o Troisiemement, il demande au compilateur d'engendrer le code assembleur produit pour ces petites sections de code. +o Enfin, il effectue a la main modifications et reglages, a la recherche des petites ameliorations possibles par rapport au code engendre par la machine. L'homme gagne parce qu'il peut utiliser la machine.'' 22..22..22.. LLaannggaaggeess aavveecc ddeess ccoommppiillaatteeuurrss ooppttiimmiissaatteeuurrss Des langages comme ObjectiveCAML, SML, CommonLISP, Scheme, ADA, Pascal, C, C++, parmi tant d'autres, ont tous des compilateurs optimiseurs librement disponibles, qui optimiseront le gros de vos programmes, et produiront souvent du code meilleur que de l'assembleur fait-main, meme pour des boucles serrees, tout en vous permettant de vous concentrer sur des details haut niveau, et sans vous interdire de gagner par la methode precedente quelques pourcents de performance supplementaire, une fois la phase de conception generale terminee. Bien sur, il existe egalement des compilateurs optimiseurs commerciaux pour la plupart de ces langages. Certains langages ont des compilateurs qui produisent du code C qui peut ensuite etre optimise par un compilateur C. C'est le cas des langages LISP, Scheme, Perl, ainsi que de nombreux autres. La vitesse des programmes obtenus est toute a fait satisfaisante. 22..22..33.. PPrroocceedduurree ggeenneerraallee aa ssuuiivvrree ppoouurr aacccceelleerreerr vvoottrree ccooddee Pour accelerer votre code, vous ne devriez traiter que les portions d'un programme qu'un outil de mesure de temps d'execution (profiler) aura identifie comme etant un goulot d'etranglement pour la performance de votre programme. Ainsi, si vous identifiez une partie du code comme etant trop lente, vous devriez +o d'abord essayer d'utiliser un meilleur algorithme; +o essayer de la compiler au lieu de l'interpreter; +o essayer d'activer les bonnes options d'optimisation de votre compilateur; +o donner au compilateur des indices d'optimisation (declarations de typage en LISP; utilisation des extensions GNU avec GCC; la plupart des compilos fourmillent d'options); +o enfin de compte seulement, se mettre a l'assembleur si necessaire. Enfin, avant d'en venir a cette derniere option, vous devriez inspecter le code genere pour verifier que le probleme vient effectivement d'une mauvaise generation de code, car il se peut fort bien que ce ne soit pas le cas: le code produit par le compilateur pourrait etre meilleur que celui que vous auriez ecrit, en particulier sur les architectures modernes a pipelines multiples! Il se peut que les portions les plus lentes de votre programme le soit pour des raisons intrinseques. Les plus gros problemes sur les architectures modernes a processeur rapide sont dues aux delais introduits par les acces memoires, manques des caches et TLB, fautes de page; l'optimisation des registres devient vaine, et il vaut mieux repenser les structures de donnees et l'enchainement des routines pour obtenir une meilleur localite des acces memoire. Il est possible qu'une approche completement differente du probleme soit alors utile. 22..22..44.. IInnssppeeccttiioonn dduu ccooddee pprroodduuiitt ppaarr llee ccoommppiillaatteeuurr Il existe de nombreuses raisons pour vouloir regarder le code assembleur produit par le compilateur. Voici ce que vous pourrez faire avec ce code: +o verifier si le code produit peut ou non etre ameliorer avec du code assembleur ecrit a la main (ou par un reglage different des options du compilateur); +o quand c'est le cas, commencer a partir de code automatiquement engendre et le modifier plutot que de repartir de zero; +o plus generalement, utilisez le code produit comme des scions a greffer, ce qui a tout le moins vous laisse permet d'avoir gratuitement tout le code d'interfacage avec le monde exterieur. +o reperer des bogues eventuels dus au compilateur lui-meme (esperons- le tres rare, quitte a se restreindre a des versions ``stables'' du compilo). La maniere standard d'obtenir le code assembleur genere est d'appeller le compilateur avec l'option -S. Cela fonctionne avec la plupart des compilateur Unix y compris le compilateur GNU C (GCC); mais a vous de voir dans votre cas. Pour ce qui est de GCC, il produira un code un peu plus comprehensible avec l'option -fverbose-asm. Bien sur, si vous souhaitez obtenir du code assembleur optimise, n'oubliez pas d'ajouter les options et indices d'optimisation appropriees! 33.. AAsssseemmbblleeuurrss 33..11.. AAsssseemmbblleeuurr eenn--lliiggnnee ddee GGCCCC Le celebre GNU C/C++ Compiler (GCC), est un compilateur 32 bits optimisant situe au coeur du projet GNU. Il gere assez bien les architectures x86 et permet d'inserer du code assembleur a l'interieur de programmes C de telle maniere que les registres puissent etre soit specifies soit laisse aux bons soins de GCC. GCC fonctionne sur la plupart des plates-formes dont Linux, *BSD, VSTa, OS/2, *DOS, Win*, etc. 33..11..11.. OOuu ttrroouuvveerr GGCCCC Le site principal de GCC est le site FTP du projet GNU: On y trouve egalement toutes les applications provenant du projet GNU. Des versions configurees ou precompilees pour Linux sont disponibles sur . Il existe un grand nombre de miroirs FTP des deux sites partout de par le monde, aussi bien que des copies sur CD-ROM. Le groupe de developpement de GCC s'est recemment scinde en deux; pour plus d'informations sur la version experimentale, egcs, voir Les sources adaptes a votre systeme d'exploitation prefere ainsi que les binaires precompiles peuvent etre trouves sur les sites FTP courants. Le portage le plus celebre de GCC pour DOS est DJGPP et il peut etre trouve dans le repertoire du meme nom sur les sites ftp. Voir: Il existe egalement un portage de GCC pour OS/2 appele EMX qui fonctionne egalement sous DOS et inclut un grand nombre de routines d'emulation Unix. Voir les sites 33..11..22.. OOuu ttrroouuvveerr ddee llaa ddooccuummeennttaattiioonn ssuurr ll''aasssseemmbblleeuurr eenn lliiggnnee aavveecc GGCCCC?? La document de GCC inclus les fichiers de documentation au format texinfo. Vous pouvez les compiler avec TeX et les imprimer, ou les convertir au format .info et les parcourir interactivement avec emacs, ou encore les convertir au format HTML, ou en a peu pres n'importe quel format (avec les outils adequats). Les fichiers .info sont generalement installes en meme temps que GCC. La section a consulter est C Extensions::Extended Asm:: La section Invoking GCC::Submodel Options::i386 Options:: peut egalement vous aider. En particulier, elle donne les noms de contraintes pour les registres du i386: abcdSDB correspondent respectivement a %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp (aucune lettre pour %esp). Le site "DJGPP Games resource" (qui n'est pas reserve aux seuls developpeurs de jeux) possede une page particuliere sur l'assembleur: Enfin, il existe une page de la Toile appelee "DJGPP Quick ASM Programming Guide", contenant des URL sur des FAQ, la syntaxe assembleur AT&T x86, des informations sur l'assembleur en ligne, et la conversion des fichiers .obj/.lib: GCC soutraite l'assemblage proprement dit a GAS et suit donc sa syntaxe (voir plus bas), cela implique que l'assembleur en ligne doit utiliser des caracteres pourcents entre apostrophes pour qu'ils soient passes a GAS. Voir la section dediee a GAS. Vous trouverez un _g_r_a_n_d nombre d'exemples instructifs dans le repertoire linux/include/asm-i386/ des sources de Linux. 33..11..33.. AAppppeelllleerr GGCCCC ppoouurr oobbtteenniirr dduu ccooddee aasssseemmbblleeuurr eenn lliiggnnee ccoorr-- rreeccttee?? Assurez-vous d'appeller gcc avec l'option -O (ou -O2, -O3, etc) pour activer les optimisations et l'assembleur en ligne. Si vous ne le faites pas, votre code pourra compiler mais ne pas s'executer correctement!! En fait (merci a Tim Potter, timbo@moshpit.air.net.au), il suffit d'utiliser l'option -fasm, faisant partie de toutes les fonctionnalites activees par l'option -O. Donc si vous avez des problemes en raison d'optimisations boguees dans votre implementation de gcc, vous pouvez toujours utiliser l'assembleur en ligne. De meme, utilisez l'option -fno-asm pour desactiver l'assembleur en ligne (on peut se demander pourquoi?). Plus generalement, les bonnes options de compilation a utiliser avec gcc sur les plates-formes x86 sont ______________________________________________________________________ gcc -O2 -fomit-frame-pointer -m386 -Wall ______________________________________________________________________ -O2 est le bon niveau d'optimisation. Les optimisations superieures generent un code un peu plus important, mais tres legerement plus rapide. De telles sur-optimisations peuvent etre utiles que dans le cas d'optimisations de boucles que vous pouvez toujours realiser en assembleur. Si vous avez besoin de faire ce genre de choses, ne le faites que pour les routines qui en ont besoin. -fomit-frame-pointer permet au code genere de se passer de la gestion inutile des pointeurs de fenetre, ce qui rend le code plus petit plus rapide et libere un registre pour de plus amples optimisations. Cette option exclue l'utilisation des outils de deboggage (gdb), mais lorsque vous les utilisez, la taille et la vitesse importent peu. -m386 genere un code plus compacte sans ralentissement notable, (moins de code signifie egalement mois d'entrees/sorties sur disque et donc une execution plus rapide). Vous pouvez egalement utiliser l'option -mpentium sur la version GCC gerant l'optimisation pour ce processeur. -Wall active toutes les mises-en-garde (warning) et vous evite de nombreuses erreurs stupides et evidentes. Pour optimiser encore plus, vous pouvez utiliser l'option -mregparm=2 et/ou les attributs de fonctions qui peuvent etre utilises mais ils peuvent dans certains cas poser de nombreux problemes lors de l'edition de liens avec du code externe (notamment les bibliotheques partagees)... Notez que vous pouvez ajoutez ces options aux options utilisees par defaut sur votre systeme en editant le fichier /usr/lib/gcc- lib/i486-linux/2.7.2.3/specs (cependant, ne rajoutez pas -Wall a ces options). 33..22.. GGAASS GAS est l'assembleur GNU, utilise par gcc. 33..22..11.. OOuu llee ttrroouuvveerr?? Au meme endroit ou vous avez trouve gcc, dans le paquetage binutils. 33..22..22.. QQuu''eesstt--ccee qquuee llaa ssyynnttaaxxee AATT&&TT Comme GAS a ete invente pour supporter un compilateur 32 bits sous unix, il utilise la syntaxe standard "AT&T", qui ressemblent assez a l'assembleur m68k. La syntaxe n'est ni pire, ni meilleur que la syntaxe "Intel". Elle est juste differente. Lorsque vous aurez l'habitude de vous en servir, vous la trouverez plus reguliere que la syntaxe Intel, quoique que legerement plus ennuyeuse aussi. Voici les points les plus importants a propos de la syntaxe de GAS: +o Les noms de registres sont prefixes avec %, de facon que les registres sont %eax, %dl et consorts au lieu de juste eax, dl, etc. Ceci rend possible l'inclusion directe de noms de symboles externes C sans risque de confusion, ou de necessite de prefixes _. +o L'ordre des operandes est source(s) d'abord, destination en dernier, a l'oppose de la convention d'intel consistant a mettre la destination en premier, les source(s) ensuite. Ainsi, ce qui en syntaxe intel s'ecrit mov ax,dx (affecter au registre ax le contentu du registre dx) s'ecrira en syntaxe att mov %dx, %ax. +o La longueur des operandes est specifiee comme suffixe du nom d'instruction. Le suffixe est b pour un octet (8 bit), w pour un mot (16 bit), et l pour un mot long (32 bit). Par exemple, la syntaxe correcte pour l'instruction ci-dessus aurait du etre movw %dx,%ax. Toutefois, gas n'est pas trop aussi strict que la syntaxe att l'exige, et le suffixe est optionel quand la longueur peut etre devinee grace aux operandes qui sont des registres, la taille par defaut etant 32 bit (avec une mise en garde quand on y fait appel). +o Les operandes immediates sont marques d'un prefixe $, comme dans addl $5,%eax (ajouter la valeur longue immediate 5 au registre %eax). +o L'absence de prefixe a une operande indique une adresse memoire; ainsi movl $foo,%eax met l'_a_d_r_e_s_s_e de la variable foo dans le registre %eax, tandis que movl foo,%eax met le contenu de la variable foo dans le registre %eax. +o L'indexation ou l'indirection se fait en mettant entre parentheses le registre d'index ou la case memoire contenant l'indirection, comme dans testb $0x80,17(%ebp) (tester le bit de poids fort de l'octet au deplacement 17 apres la case pointee par %ebp). Un programme existe pour vous aider a convertir des programmes ecrits avec la syntaxe TASM en syntaxe AT&T. Voir GAS possede une documentation complete au format TeXinfo, qui est distribuee entre autre avec les sources. Vous pouvez parcourir les pages .info qui en sont extraites avec Emacs. Il y avait aussi un fichier nomme gas.doc ou as.doc disponible autour des sources de GAS, mais il a ete fusionne avec la documentation TeXinfo. Bien sur, en cas de doute, l'ultime documentation est constituee par les sources eux-memes! Une section qui vous interessera particulierement est Machine Dependencies::i386-Dependent:: Les sources de Linux dont un bon exemple: regardez dans le repertoire linux/arch/i386 les fichiers suivants: kernel/*.S, boot/compressed/*.S, mathemu/*.S Si vous codez ce genre de chose, un paquetage de thread, etc vous devriez regarder d'autres langages (OCaml, gforth, etc), ou des paquetages sur les thread (QuickThreads, pthreads MIT, LinuxThreads, etc). Enfin generer a partir d'un programme C du code assembleur peut vous montrer le genre d'instructions que vous voulez. Consultez la section ``Avez-vous besoin de l'assembleur?'' au debut de ce document. 33..22..33.. mmooddee 1166 bbiittss lliimmiittee GAS est un assembleur 32 bits, concu pour assembler le code produit par un compilateur 32 bits. Il ne reconnait que d'une maniere limite le mode 16 bits du i386, en ajoutant des prefixes 32 bits aux instructions; vous ecrivez donc en realite du code 32 bits, qui s'execute en mode 16 bits sur un processeur 32 bits. Dans les deux modes, il gere les registres 16 bits, mais pas l'adressage 16 bits. Utilisez les instructions .code16 et .code32 pour basculer d'un mode a l'autre. Notez que l'instruction assembleur en ligne asm(".code16\n") autorisera gcc a generer du code 32 bits qui fonctionnera en mode reel! Le code necessaire pour que GAS gere le mode 16 bits aurait ete ajoute par Bryan Ford (a confirmer?). Toutefois, ce code n'est present dans aucune distribution de GAS que j'ai essayee (jusqu'a binutils-2.8.1.x) ... plus d'informations a ce sujet seraient les bienvenues dans ce HowTo. Une solution bon marche pour inserer quelques instructions 16-bit non reconnues pas GAS consiste a definir des macros (voir plus bas) qui produisent directement du code binaire (avec .byte), et ce uniquement pour les rares instructions 16 bits dont vous avez besoin (quasiment aucunes, si vous utilisez le .code16 precedement decrit, et pouvez vous permettre de supposer que le code fonctionnera sur un processeur 32 bits). Pour obtenir le systeme de codage correct, vous pouvez vous inspirer des assembleurs 16 bits. 33..33.. GGAASSPP GASP est un preprocesseur pour GAS. Il ajoute des macros et une syntaxe plus souple a GAS. 33..33..11.. OOuu ttrroouuvveerr ggaasspp?? gasp est livre avec gas dans le paquetage binutils GNU. 33..33..22.. CCoommmmeenntt iill ffoonnccttiioonnnnee?? Cela fonctionne comme un filtre, tout comme cpp et ses variantes. Je ne connais pas les details, mais il est livre avec sa propre documentation texinfo, donc consultez-la, imprimez-la, assimilez-la. La combinaison GAS/GASP me semble etre un macro-assembleur standard. 33..44.. NNAASSMM Du projet Netwide Assembler est issu encore un autre assembleur, ecrit en C, qui devrait etre assez modulaire pour supporter toutes les syntaxes connues et tous les formats objets existants. 33..44..11.. OOuu ttrroouuvveerr NNAASSMM?? Les versions binaires se trouvent sur votre miroir sunsite habituel dans le repertoire devel/lang/asm/. Il devrait egalement etre disponible sous forme d'archive .rpm ou .deb parmi les contributions a votre distribution preferee RedHat ou Debian. 33..44..22.. SSoonn rroollee Au moment de l'ecriture de ce HOWTO, NASM en est a la version 0.96. La syntaxe est a la Intel. Une gestion de macros est integree. Les formats objets reconnus sont bin, aout, coff, elf, as86, (DOS) obj, win32, et rdf (leur propre format). NASM peut etre utilisee comme assembleur pour le compilateur libre LCC. Comme NASM evolue rapidement, ce HowTo peut ne pas etre a jour a son sujet. A moins que vous n'utilisiez BCC comme compilateur 16 bit (ce qui depasse le cadre de ce document), vous devriez utiliser NASM plutot que AS86 ou MASM, car c'est un logiciel libre avec un excellent service apres-don, qui tourne sur toutes plateformes logicielles et materielles. Note: NASM est egalement livre avec un desassembleur, NDISASM. Son analyseur "grammatical", ecrit a la main, le rend beaucoup plus rapide que GAS; en contrepartie, il ne reconnait qu'une architecture, en comparaison de la plethore d'architectures reconnues par GAS. Pour les plates-formes x86, NASM semble etre un choix judicieux. 33..55.. AASS8866 AS86 est un assembleur 80x86, a la fois 16 et 32 bits, faisant partie du compilateur C de Bruce Evans (BCC). Il possede une syntaxe a la Intel. 33..55..11.. WWhheerree ttoo ggeett AASS8866 Une version completement depassee de AS86 est diffusee par HJLu juste pour compiler le noyau Linux, dans un paquetage du nom de bin86 (actuellement version 0.4) disponible dans le repertoire GCC des sites FTP Linux. Je deconseille son utilisation pour toute autre chose que compiler Linux. Cette version ne reconnait qu'un format de fichiers minix modifie, que ne reconnaissent ni les binutils GNU ni aucun autre produit. Il possede de plus certains bogues en mode 32 bits. Ne vous en servez donc vraiment que pour compiler Linux. Les versions les plus recentes de Bruce Evans (bde@zeta.org.au) est diffusee avec la distribution FreeBSD. Enfin, elles l'etaient! Je n'ai pas pu trouver les sources dans la distribution 2.1. Toutefois, vous pouvez trouver les sources dans Le projet Linux/8086 (egalement appele ELKS) s'est d'une certaine maniere chargee de maintenir bcc (mais je ne crois pas qu'ils aient inclus les patches 32 bits). Voir les sites et . Entre autres choses, ces versions plus recentes, a la difference de celle de HJLu, gerent le format a.out de Linux; vous pouvez donc effectuer des editions de liens avec des programmes Linux, et/ou utiliser les outils habituels provenant du paquetage binutils pour manipuler vos donnees. Cette version peut co-exister sans probleme avec les versions precedentes (voir la question a ce sujet un peu plus loin). La version du 12 mars 1995 de BCC ainsi que les precedentes a un probleme qui provoque la generation de toutes les operations d'empilement/depilement de segments en 16 bits, ce qui est particulierement ennuyant lorsque vous developpez en mode 32 bits. Un patch est diffuse par le projet Tunes a partir du lien suivant: files/tgz/tunes.0.0.0.25.src.tgz ou dans le repertoire LLL/i386/. Le patch peut egalement etre directement recupere sur Bruce Evans a accepte ce patch, donc si une version plus recente de BCC existe, le patch devrait avoir ete integre... 33..55..22.. CCoommmmee aappppeelllleerr ll''aasssseemmbblleeuurr?? Voici l'entree d'un Makefile GNU pour utiliser bcc pour transformer un fichier assembleur .s a la fois en un objet a.out GNU .o et un listing .l: ______________________________________________________________________ %.o %.l: %.s bcc -3 -G -c -A-d -A-l -A\*(dR*.l -o \*(dR*.o \*(dR< ______________________________________________________________________ Supprimez %.l, -A-l, et -A$*.l, si vous ne voulez pas avoir de listing. Si vous souhaitez obtenir autre chose que du a.out GNU, consultez la documentation de bcc concernant les autres formats reconnus et/ou utilisez le programme objcopy du paquetage binutils. 33..55..33.. OOuu ttrroouuvveerr ddee llaa ddooccuummeennttaattiioonn Les documentations se trouvent dans le paquetage bcc. Des pages de manuel sont egalement disponibles quelque part sur le site de FreeBSD. Dans le doute, les sources sont assez souvent une bonne documentation: ce n'est pas tres commente mais le style de programmation est tres simple. Vous pouvez essayer de voir comment as86 est utilise dans Tunes 0.0.0.25... 33..55..44.. vveerrssiioonn QQuuee ffaaiirree ssii jjee nnee ppeeuuxx pplluuss ccoommppiilleerr LLiinnuuxx aavveecc cceettttee nnoouuvveellllee Linus est submerge par le courrier electronique et mon patch pour compiler Linux avec un as86 a.out n'a pas du lui parvenir (!). Peu importe: conservez le as86 provenant du paquetage bin86 dans le repertoire /usr/bin, et laissez bcc installer le bon as86 en tant que /usr/local/libexec/i386/bcc/as comme que de droit. Vous n'aurez jamais besoin d'appeler explicitement ce dernier, car bcc se charge tres bien de tout, y compris la conversion en a.out Linux, lorsqu'il est appele avec les bonnes options. Assemblez les fichiers uniquement en passant par bcc, et non pas en appelant as86 directement. 33..66.. AAuuttrreess aasssseemmbblleeuurrss Il s'agit d'autres possibilites, qui sortent de la voie ordinaire, pour le cas ou les solutions precedentes ne vous conviennent pas (mais je voudrais bien savoir pourquoi?), que je ne recommande pas dans les cas habituels, mais qui peuvent se montrer fort utiles si l'assembleur doit faire partie integrante du logiciel que vous concevez (par exemple un systeme d'exploitation ou un environnement de developpement). 33..66..11.. LL''aasssseemmbblleeuurr ddee WWiinn3322FFoorrtthh Win32Forth est un systeme ANS FORTH 32 bit _l_i_b_r_e qui fonctionne sous Win32s, Win95, Win/NT. Il comprend un assembleur 32 bit libre (sous forme prefixe ou postfixe) integree au langage FORTH. Le traitement des macro est effectue en utilisant toute la puissance du langage reflexif FORTH. Toutefois, le seul contexte d'entree et sortie reconnu actuellement est Win32For lui-meme (aucune possibilite d'obtenir un fichier objet, mais vous pouvez toujours l'ajouter par vous-meme, bien sur). Vous pouvez trouver Win32For a l'adresse suivante: 33..66..22.. TTeerrssee Terse est un outil de programmation qui fournit _L_A syntaxe assembleur la plus compacte pour la famille des processeur x86! Voir le site . Ce n'est cependant pas un logiciel libre. Il y aurait eu un clone libre quelque part, abandonne a la suite de mensongeres allegations de droits sur la syntaxe, que je vous invite a ressusciter si la syntaxe vous interesse. 33..66..33.. AAsssseemmbblleeuurrss nnoonn lliibbrreess eett//oouu nnoonn 3322 bbiittss Vous trouverez un peu plus d'informations sur eux, ainsi que sur les bases de la programmation assembleur sur x86, dans la FAQ de Raymond Moon pour le forum comp.lang.asm.x86. Voir Remarquez que tous les assembleurs DOS devraient fonctionner avec l'emulateur DOS de Linux ainsi qu'avec d'autres emulateurs du meme genre. Aussi, si vous en possedez un, vous pouvez toujours l'utiliser a l'interieur d'un vrai systeme d'exploitation. Les assembleurs sous DOS assez recents gerent egalement les formats de fichiers objets COFF et/ou des formats geres par la bibliotheque GNU BFD de telle maniere que vous pouvez les utiliser en conjonction avec les outils 32 bits libres, en utilisant le programme GNU objcopy (du paquetage binutils) comme un filtre de conversion. 44.. MMeettaa--pprrooggrraammmmaattiioonn//mmaaccrroo--ttrraaiitteemmeenntt La programmation en assembleur est particulierement penible si ce n'est pour certaines parties critiques des programmes. Pour travail donne, il faut l'outil approprie; ne choisissez donc pas l'assembleur lorsqu'il ne correspond pas au probleme a resoudre: C, OCAML, perl, Scheme peuvent etre un meilleur choix dans la plupart des cas. Toutefois, il y a certains cas ou ces outils n'ont pas un controle suffisamment fin sur la machine, et ou l'assembleur est utile ou necessaire. Dans ces cas, vous apprecierez un systeme de programmation par macros, ou un systeme de meta-programmation, qui permet aux motifs repetitifs d'etre factorises chacun en une seule definition indefiniment reutilisable. Cela permet une programmation plus sure, une propagation automatique des modifications desdits motifs, etc. Un assembleur de base souvent ne suffit pas, meme pour n'ecrire que de petites routines a lier a du code C. 44..11.. DDeessccrriippttiioonn Oui, je sais que cette partie peut manquer d'informations utiles a jour. Vous etes libres de me faire part des decouvertes que vous auriez du faire a la dure... 44..11..11.. GGCCCC GCC vous permet (et vous oblige) de specifier les contraintes entre registres assembleurs et objets C, pour que le compilateur puisse interfacer le code assembleur avec le code produit par l'optimiseur. Le code assembleur en ligne est donc constitue de motifs, et pas forcement de code exact. Et puis, vous pouvez mettre du code assembleur dans des macro- definitions de CPP ou des fonctions "en-ligne" (inline), de telle maniere que tout le monde puisse les utiliser comme n'importe quelle fonction ou macro C. Les fonctions en ligne ressemblent enormement aux macros mais sont parfois plus propres a utiliser. Mefiez-vous car dans tous ces cas, le code sera duplique, et donc seules les etiquettes locales (comme 1:) devraient etre definies dans ce code assembleur. Toutefois, une macro devrait permettre de passer en parametre le nom eventuellement necessaire d'une etiquette definie non localement (ou sinon, utilisez des methodes supplementaires de meta- programmation). Notez egalement que propager du code assembleur en- ligne repandra les bogues potentiels qu'il contiendrait, aussi, faites doublement attention a donner a GCC des contraintes correctes. Enfin, le langage C lui-meme peut etre considere comme etant une bonne abstraction de la programmation assembleur, qui devrait vous eviter la plupart des difficultes de la programmation assembleur. Mefiez-vous des optimisations consistant a passer les arguments en utilisant les registres: cela interdit aux fonctions concernees d'etre appelees par des routines exterieurs (en particulier celles ecrites a la main en assembleur) d'une maniere standard; l'attribut asmlinkage devrait empecher des routines donnees d'etre concernees par de telles options d'optimisation. Voir les sources du noyau Linux pour avoir des exemples. 44..11..22.. GGAASS GAS a quelques menues fonctionnalite pour les macro, detaillees dans la documentation TeXinfo. De plus J'ai entendu dire que les versions recentes en seront dotees... voir les fichiers TeXinfo). De plus, tandis que GCC reconnait les fichiers en .s comme de l'assembleur a envoyer dans GAS, il reconnait aussi les fichiers en .S comme devant etre filtrer a travers CPP avant d'etre envoyer a GAS. Au risque de me repeter, je vous convie a consulter les sources du noyau Linux. 44..11..33.. GGAASSPP Il ajoute toutes les fonctionnalites habituelles de macro a GAS. Voir sa documentation sous forme texinfo. 44..11..44.. NNAASSMM NASM possede aussi son systeme de macros. Consultez sa documentation. Si vous avez quelqu'idee lumineuse, contactez les auteurs, etant donne qu'ils sont en train de developper NASM activement. Pendant ce meme temps, lisez la partie sur les filtres externes un peu plus loin. 44..11..55.. AASS8866 Il possede un systeme simple de macros, mais je n'ai pas pu trouver de documentation. Cependant, les sources sont d'une approche particulierement aisee, donc si vous etes interesse pour en savoir plus, vous devriez pouvoir les comprendre sans probleme. Si vous avez besoin d'un peu plus que des bases, vous devriez utiliser un filtre externe (voir un peu plus loin). 44..11..66.. AAuuttrreess aasssseemmbblleeuurrss +o Win32FORTH: CODE et END-CODE sont des macros qui ne basculent pas du mode interpretation au mode compilation; vous aurez donc acces a toute la puissance du FORTH lors de l'assemblage. +o Tunes: cela ne fonctionne pas encore, mais le langage Scheme est un langage de tres haut niveau qui permet une meta-programmation arbitraire. 44..22.. FFiillttrreess eexxtteerrnneess Quelque soit la gestion des macros de votre assembleur, ou quelque soit le langage que vous utilisez (meme le C), si le langage n'est pas assez expressif pour vous, vous pouvez faire passer vos fichier a travers un filtre externe grace a une regle comme suit dans votre Makefile: ______________________________________________________________________ %.s: %.S autres_dependances \*(dR(FILTER) \*(dR(FILTER_OPTIONS) < \*(dR< > \*(dR@ ______________________________________________________________________ 44..22..11.. CCPPPP CPP n'est vraiment pas tres expressif, mais il suffit pour les choses faciles, et il est appele d'une maniere transparente par GCC. Comme exemple de limitation, vous ne pouvez pas declarer d'objet de facon a ce qu'un destructeur soit automatiquement appele a la fin du bloc ayant declare l'objet. Vous n'avez pas de diversions ou de gestion de portee des variables, etc. CPP est livre avec tout compilateur C. Si vous pouvez faire sans, n'allez pas chercher CPP (bien que je me demande comment vous pouvez faire). 44..22..22.. MM44 M4 vous donne la pleine puissance du macro-traitement, avec un langage Turing-equivalent, recursivite, expressions regulieres, etc. Vous pouvez faire avec tout ce que cpp ne peut faire. Voir macro4th/This4th que l'on trouve sur dans Reviewed/ ANS/ (?), ou les sources de Tunes 0.0.0.25 comme exemple de programmation avancee en utilisant m4. Toutefois, le systeme de citation est tres penible a utiliser et vous oblige a utiliser un style de programmation par fonctions recursives avec passage explicite de continuation (CPS) pour toute programmation _a_v_a_n_c_e_e (ce qui n'est pas sans rappeler a TeX -- au fait quelqu'un a- t-il deja essaye d'utiliser TeX comme macro-processeur pour autre chose que de la mise-en-page?). Toutefois, ce n'est pas pire que cpp qui ne permet ni citation ni recursivite. La bonne version de m4 a recuperer est GNU m4 1.4 (ou ulterieure si elle existe). C'est celle qui contient le plus de fonctionnalite et le moins de bogues ou de limitations. m4 est concu pour etre intrinsequement lent pour toute utilisation sauf la plus simple; cela suffit sans aucun doute pour la plupart des programmes en assembleur (vous n'allez quand meme pas ecrire des millions de lignes en assembleur, si?). 44..22..33.. MMaaccrroo--ttrraaiitteemmeenntt aavveecc vvoottrree pprroopprree ffiillttrree Vous pouvez ecrire votre propre programme d'expansion de macro avec les outils courants comme perl, awk, sed, etc. C'est assez rapide a faire et vous pouvez tout controler. Mais bien toute puissance dans le macro-traitement doit se gagner a la dure. 44..22..44.. MMeettaa--pprrooggrraammmmaattiioonn Plutot que d'utiliser un filtre externe qui effectue l'expansion des macros, une maniere de realiser cela est d'ecrire des programmes qui ecrivent d'autres programmes, en partie ou en totalite. Par exemple, vous pourriez utiliser un programme generant du code source +o pour creer des tables de sinus/cosinus (ou autre), +o pour decompiler un fichier binaire en source annote annote, +o pour compiler vos bitmaps en des routines d'affichage rapides, +o pour extraire de la documentation, du code d'initilisation ou finalisation, des tables de descriptions, aussi bien que du code normal depuis les memes fichiers sources; +o pour utiliser une technique specifique de production de code, produite avec un script perl/shell/scheme +o pour propager des donnees definies en une seule fois dans de nombreux morceaux de code ou tables avec references croisees. +o etc. Pensez-y! 44..22..44..11.. BBaacckkeennddss pprroovveennaanntt ddee ccoommppiillaatteeuurr eexxiissttaannttss Des compilateurs comme SML/NJ, Objective CAML, MIT-Scheme, etc, ont leur propre generateur de code assembleur, que vous pouvez ou non utiliser, si vous souhaitez generer du code semi-automatiquement depuis les langages correspondants. 44..22..44..22.. LLee NNeeww--JJeerrsseeyy MMaacchhiinnee--CCooddee TToooollkkiitt Il s'agit projet utilisant le langage de programmation Icon pour batir une base de code de manipulation d'assembleur. Voir 44..22..44..33.. TTuunneess Le projet de systeme d'exploitation OS developpe son propre assembleur comme etant une extension du langage Scheme. Il ne fonctionne pas encore totalement, de l'aide est bienvenue. L'assembleur manipule des arbres de syntaxes symboliques, de telle maniere qu'il puisse servir comme base d'un traducteur de syntaxe assembleur, un desassembleur, l'assembleur d'un compilateur, etc. Le fait qu'il utile un vrai langage de programmation puissant comme Scheme le rend imbatable pour le macro-traitement et pour la meta- programmation. 55.. CCoonnvveennttiioonnss dd''aappppeell 55..11.. LLiinnuuxx 55..11..11.. EEddiittiioonn ddee lliieennss aavveecc GGCCCC C'est la solution la plus pratique. Consultez la documentation de gcc et prenez exemple sur les sources du noyau Linux (fichiers .S qui sont utilises avec gas, non pas as86). Les arguments 32 bits sont empiles dans la pile vers le bas dans l'ordre inverse de l'ordre syntaxique (c'est-a-dire qu'on accede aux arguments ou les depile dans l'ordre syntaxique), au-dessus de l'adresse de retour 32 bits. %ebp, %esi, %edi, %ebx doivent etre conserves par l'appele, les autres registres peuvent etre detruits; %eax doit contenir le resultat, ou %edx:%eax pour des resultats sur 64 bits. Pile virgule flottante: je ne suis pas sur, mais je pense que le resultat se trouve dans st(0), la pile etant a la discretion de l'appele. Notez que GCC possede certaines options pour modifier les conventions d'appel en reservant certains registres, en mettant les arguments dans des registres, en supposant que l'on ne possede pas de FPU, etc. Consultez les pages .info concernant le i386. Il faut prendre garde a declarer l'attribut cdecl pour une fonction qui suit la convention standard GCC (je ne sais pas exactement ce que cela produit avec des conventions modifiees). Consultez la documentation GCC dans la section: C Extensions::Extended Asm:: 55..11..22.. PPrroobblleemmeess EELLFF eett aa..oouutt Certains compilateurs C ajoutent un underscore avant tout symbole, alors que d'autres ne le font pas. En particulier, la version GCC a.out effectue ce genre d'ajouts, alors que la version ELF ne le fait pas. Si vous etes confronte a ce probleme, regardez comment des paquetages existants traitent le problemes. Par exemple, recuperer une ancienne arborescence des sources de Linux, Elk, les qthreads ou OCAML... Vous pouvez egalement redefinir le renommage implicite de C en assembleur en ajoutant les instructions suivantes: ______________________________________________________________________ void truc asm("machin") (void); ______________________________________________________________________ pour s'assurer que la fonction C truc sera reellement appelee machin en assembleur. Remarquez que l'outil objcopy, du paquetage binutils, devrait vous permettre de transformer vos fichiers objets a.out en objets ELF et peut-etre inversement dans certains cas. D'une maniere plus generale, il vous permet d'effectuer de nombreuses conversions de formats de fichiers. 55..11..33.. AAppppeellss ssyysstteemmeess ddiirreeccttss Il n'est absolument pas recommande d'effectuer de tels appels par ce que leurs conventions peuvent changer de temps en temps, ou d'un type de noyau a un autre (cf L4Linux), de plus, ce n'est pas portable, difficile a ecrire, redondant avec l'effort entrepris par libc, et enfin, cela empeche les corrections et les extensions effectuees a travers la libc, comme par exemple avec le programme zlibc qui realise une decompression a la volee de fichiers compresses avec gzip. La maniere standard et recommendee d'effectuer des appels systemes est et restera de passer par la libc. Les objets partages devraient reduire l'occupation memoire des programmes, et si vous souhaitez absolument avoir de petits executables, utilisez #! avec un interpreteur qui contiendra tout ce que vous ne voulez pas mettre dans vos binaires. Maintenant, si pour certaines raisons, vous ne souhaitez pas effectuer une edition des liens avec la libc, recuperez-la et essayez de comprendre comment elle fonctionne! Apres tout, vous pretendez bien la remplacer non? Vous pouvez aussi regarder comment eforth 1.0c le fait. Les sources de Linux sont fort utiles, en particulier le fichier d'en- tete asm/unistd.h qui decrit comment sont effectues les appels systeme... Le principe general est d'utiliser l'instruction int $0x80 avec le numero de l'appel systeme __NR_machin (regarder dans asm/unistd.h) dans %eax, et les parametres (jusqu'a cinq) dans %ebx, %ecx, %edx, %esi, %edi. Le resultat est renvoye dans %eax avec un resultat negatif etant l'erreur dont l'oppose est tranfere par la libc dans errno. La pile utilisateur n'est pas modificee donc n'avez pas besoin d'en avoir une correcte lors de l'appel. 55..11..44.. EEnnttrreeeess//ssoorrttiieess ssoouuss LLiinnuuxx Si vous souhaitez effectuer des entrees/sorties directement sous Linux, soit il s'agit de quelque chose de tres simple qui n'a pas besoin de specificites du systeme et dans ce cas la, consultez le mini-HOWTO IO-Port-Programming, ou alors vous devez creer un nouveau gestionnaire de peripherique et vous devriez alors lire quelques documents sur les meandres du noyau, le developpement de gestionnaires de peripheriques, les modules du noyau, etc. Vous trouverez d'excellents HOWTO ou autres documents du projet LDP. Plus particulierement, si vous souhaitez realiser des programmes graphiques, rejoignez le projet GGI: Dans tous les cas, vous devriez plutot utiliser l'assembleur en ligne de GCC avec les macros provenant des fichiers linux/asm/*.h que d'ecrire des sources en assembleur pur. 55..11..55.. AAcccceeddeerr aauuxx ggeessttiioonnnnaaiirreess 1166 bbiittss aavveecc LLiinnuuxx//ii338866 De telles choses sont theoriquement possibles (preuve: voir comment DOSEMU permet a des programmes d'acceder au port serie), et j'ai entendu des rumeurs que certaines personnes le font (avec le gestionnaire PCI? Acces aux cartes VESA? PnP ISA? Je ne sais pas). Si vous avez de plus amples precisions a ce sujet, soyez les bienvenus. Le bon endroit a regarder est les sources du noyau, les sources de DOSEMU (et des autres programmes se trouvant dans le repertoire DOSEMU ), ainsi que les sources d'autres programmes bas niveaux (peut-etre GGI s'il gere les cartes VESA). En fait, vous devez utiliser soit le mode protege 16 bits, soit le mode vm86. Le premier est plus simple a configurer mais il ne fonctionne qu'avec du code ayant un comportement propre qui n'effectue pas d'arithmetique de segments ou d'adressage absolu de segment (en particulier pour l'adressage du segment 0), a moins que par chance tous les segments utilises peuvent etre configure a l'avance dans le LDT. La seconde possiblite permet d'etre plus "compatibles" avec les environnements 16 bits mais il necessite une gestion bien plus compliquee. Dans les deux cas, avant de sauter sur le code 16 bits, vous devez: +o mmapper toute adresse absolue utilisee dans le code 16 bits (comme la ROM, les tampons video, les adresses DMA et les entrees/sorties passant des zones de memoires mappees) a partir de /dev/mem dans votre espace d'adressage de votre processus. +o configurer le LDT et/ou le moniteur en mode vm86. +o demander au noyau les droits d'acces necessaires pour les entrees/sorties (voir plus haut). Encore une fois, lisez attentivement les codes sources situes dans le repertoire de DOSEMU et consorts, en particulier ces mini-emulateurs permettant de faire tourner des programmes ELKS et/ou des .COM assez simples sous Linux/i386. 55..22.. DDOOSS La plupart des emulateurs DOS sont livres avec certaines interfaces d'acces aux services DOS. Lisez leur documentation a ce sujet, mais bien souvent, ils ne font que simuler int $0x21 et ainsi de suite, donc c'est comme si vous etiez en mode reel (je doute qu'ils aient de possibilites de fonctionner avec des operandes 32 bits: ils ne font que reflechir l'interruption dans le mode reel ou dans le gestionnaire vm86). Certaines documentations concernant DPMI (ou ses variantes peuvent) etre trouvees sur DJGPP est livre avec son propre sous-ensemble, derive, ou remplacement (limite) de la glibc. Il est possible d'effectuer une compilation croisee de Linux vers DOS. Consultez le repertoire devel/msdos/ de votre miroir FTP de sunsite.unc.edu. Voir egalement le dos-extender MOSS du projet Flux d'utah. D'autres documentations et FAQ sont plus consacres a DOS. Nous deconseillons le developpement sous DOS. 55..33.. WWiinnddaauubbeerriieess...... Heu, ce document ne traite que de libre logiciel. Telephonez-moi lorsque Windaube le deviendra ou du moins ses outils de developpement! En fait, apres tout, cela existe: Cygnus Solutions a developpe la bibliotheque cygwin32.dll pour que les programmes GNU puissent fonctionner sur les machines MicroMerdiques. Donc, vous pouvez utiliser GCC, GAS et tous les outils GNU ainsi que bon nombre d'applications Unix. Consultez leur site Web. Je (Fare) ne souhaite pas m'etendre sur la programmation sous Windaube, mais je suis sur que vous trouverez tout un tas d'informations partout... 55..44.. VVoottrree pprroopprree ssyysstteemmee dd''eexxppllooiittaattiioonn Le controle sur le systeme etant ce qui attire de nombreux programmeurs vers l'assembleur, une premisse ou un corollaire naturel de son utilisation est la volonte de developper son propre systeme d'exploitation. Remarquons tout d'abord que tout systeme permettant son auto-developpement pourrait etre qualifie de systeme d'exploitation, combien meme tournerait-il au-dessus d'un autre systeme sur lequel il se dechargerait de la gestion du multitache (Linux sur Mach) ou des entrees/sorties (OpenGenera sur Digital Unix), etc. Donc, pour simplifier le debogage, vous pouvez souhaiter developper votre systeme d'exploitation comme etant un processus fonctionnant sous Linux (au prix d'un certain ralentissement), puis, utiliser le Flux OS kit (qui permet l'utilisation des drivers Linux et BSD dans votre propre systeme d'exploitation) pour le rendre independant. Lorsque votre systeme est stable, il est toujours temps d'ecrire vos propres gestionnaires de materiels si c'est vraiment votre passion. Ce HowTo ne couvrira pas des sujets comme le code de chargement du systeme, le passage en mode 32 bits, la gestion des interruptions, les bases concernant les horreurs des processeurs Intel (mode protege, V86/R86), la definition de votre format d'objets ou de vos conventions d'appel. L'endroit ou vous pourrez trouver le plus d'informations concernant tous ces sujets est le code source de systeme deja existants. Un grand nombre de pointeurs se trouvent dans la page: 66.. AA ffaaiirree eett ppooiinntteeuurrss +o completer les sections incompletes; +o ajouter des pointeurs sur des programmes et des documentations; +o ajouter des exemples de tous les jours pour illustrer la syntaxe, la puissance et les limitation de chacune des solutions proposees; +o demander aux gens de me donner un coup de main; +o trouver quelqu'un qui a assez de temps pour prendre en charge la maintenance de ce HOWTO; +o peut-etre dire quelques mots sur l'assembleur d'autres plates- formes? +o Quelques pointeurs (en plus de ceux qui se trouvent dans ce document) +o pages de manuel pour pentium +o hornet.eng.ufl.edu pour les codages assembleurs +o ftp.luth.se +o PM FAQ +o Page Assembleur 80x86 +o Courseware +o programmation de jeux +o experiences de programmation sous Linux exclusivement en assembleur +o Et bien sur, utilisez vos outils habituels de recherche sur Internet pour trouver les informations. Merci de m'envoyer tout ce que vous trouvez d'interessant. Signature de l'auteur: -- , , _ v ~ ^ -- -- -- Fare -- rideau@clipper.ens.fr -- Francois-Rene Rideau -- +)ang-Vu Ban -- -- ' / . -- Join the TUNES project for a computing system based on computing freedom! TUNES is a Useful, Not Expedient System WWW page at URL: http://www.eleves.ens.fr:8080/home/rideau/Tunes/ .