Assembly HOWTO
Francois-Rene Rideau
[email protected]
v0.4l, 16 Novembre 1997
(Version francaise realisee par Eric Dumas
[email protected]
[email protected], et Fare Rideau
[email protected], 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
<
http://sunsite.unc.edu/LDP/COPYRIGHT.html>.
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 <mailto:
[email protected]>) ainsi que de Paul
Anderson <mailto:
[email protected]>.
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
<
http://www.eleves.ens.fr:8080/home/rideau/Assembly-HOWTO> ou
<
http://www.eleves.ens.fr:8080/home/rideau/Assembly-HOWTO.sgml>
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):
<
ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/> (?)
La version francaise de ce document peut etre trouvee sur le site
<
ftp://ftp.ibp.fr/pub/linux/french/HOWTO/>
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...
<
http://www2.dgsys.com/~raymoon/faq/asmfaq.zip>
+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 <
[email protected]> 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 <mailto:
[email protected]> pour Linux
+o Bruce Evans <mailto:
[email protected]> pour bcc d'ou as86 est extrait
+o Simon Tatham <mailto:
[email protected]> et Julian Hall
<mailto:
[email protected]> pour NASM.
+o Jim Neil <mailto:
[email protected]> pour Terse
+o Greg Hankins <mailto:
[email protected]> pour la coordination
des HOWTOs
+o Raymond Moon <mailto:
[email protected]> pour sa FAQ
+o Eric Dumas <mailto:
[email protected]> pour la traduction initiale
en francais... (l'auteur, francais, est le premier attriste de
devoir ecrire l'original en anglais)
+o Paul Anderson <mailto:
[email protected]> et Rahim Azizarab
<mailto:
[email protected]> 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:
<
ftp://prep.ai.mit.edu/pub/gnu/> On y trouve egalement toutes les
applications provenant du projet GNU. Des versions configurees ou
precompilees pour Linux sont disponibles sur
<
ftp://sunsite.unc.edu/pub/Linux/GCC/>. 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
<
http://www.cygnus.com/egcs/>
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:
<
http://www.delorie.com/djgpp/>
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
<
http://www.leo.org/pub/comp/os/os2/gnu/emx+gcc/>
<
http://warp.eecs.berkeley.edu/os2/software/shareware/emx.html>
<
ftp://ftp-os2.cdrom.com/pub/os2/emx09c/>
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:
<
http://www.rt66.com/~brennan/djgpp/djgpp_asm.html>
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:
<
http://remus.rutgers.edu/~avly/djasm.html>
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,
[email protected]), 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
<
ftp://x2ftp.oulu.fi/pub/msdos/programming/convert/ta2asv08.zip>
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??
<
http://www.cryogen.com/Nasm>
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 (
[email protected]) 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
<http:///www.eleves.ens.fr:8080/home/rideau/files/bcc-95.3.12.src.tgz>
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
<
http://www.linux.org.uk/Linux8086.html> et <
ftp://linux.mit.edu/>.
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
<
http://www.eleves.ens.fr:8080/home/rideau/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
<
http://www.eleves.ens.fr:8080/home/rideau/files/as86.bcc.patch.gz>
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: <
ftp://ftp.forth.org/pub/Forth/win32for/>
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
<
http://www.terse.com>. 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
<
http://www2.dgsys.com/~raymoon/faq/asmfaq.zip>
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
<
ftp://ftp.forth.org/pub/Forth/> 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
<
http://www.cs.virginia.edu/~nr/toolkit/>
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.
<
http://www.eleves.ens.fr:8080/home/rideau/Tunes/>
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
<
ftp://ftp.forth.org/pub/Forth/Linux/linux-eforth-1.0c.tgz> 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:
<
http://synergy.caltech.edu/~ggi/> <
http://sunserver1.rz.uni-
duesseldorf.de/~becka/doc/scrdrv.html>
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
<
ftp://tsx-11.mit.edu/pub/linux/ALPHA/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 <
ftp://x2ftp.oulu.fi/pub/msdos/programming/>
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
<
http://www.cygnus.com> 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 <
http://ww.cs.utah.edu/projects/flux/> (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:
<
http://www.eleves.ens.fr:8080/home/rideau/Tunes/Review/OSes.html>
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
<
http://www.intel.com/design/pentium/manuals/>
+o hornet.eng.ufl.edu pour les codages assembleurs
<
http://www.eng.ufl.edu/ftp>
+o ftp.luth.se <
ftp://ftp.luth.se/pub/msdos/demos/code/>
+o PM FAQ <
ftp://zfja-gate.fuw.edu.pl/cpu/protect.mod>
+o Page Assembleur 80x86 <
http://www.fys.ruu.nl/~faber/Amain.html>
+o Courseware <
http://www.cit.ac.nz/smac/csware.htm>
+o programmation de jeux
<
http://www.ee.ucl.ac.uk/~phart/gameprog.html>
+o experiences de programmation sous Linux exclusivement en
assembleur <
http://bewoner.dma.be/JanW>
+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 --
[email protected] -- 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/