Réseau Libre-entreprise : 2le | Code Lutin | Easter-eggs | eLeDo | Freeskop | iScream.Net | Les Développements Durables | LibrenBerry | Open Via | Praksys | Nereide | Eitic | Entr'ouvert Laboratoire Libre-entreprise
logo banniere easter-eggs.org pixel pixel Visiter Easter-Eggs.com
proposer un article intercal Envoyer un e-Mail a Easter-Eggs.org intercal Consulter le plan du site intercal administration du site intercal Retour a la page d'accueil
pixel
pixel
pixel Vous êtes ici : Logiciels Libres > Assembleur x86, 1ère partie
pixel
pixel
English

Autour d’Easter-eggs
pixel pixel puce Coups de coeur
pixel pixel puce Débats & travaux en cours
pixel pixel puce Projets

L’association
pixel
pixel pixel L’ensemble des articles relatifs à l’association Easter-eggs.org.
pixel
pixel pixel puce Assemblées générales
pixel pixel puce Comptabilité
pixel pixel puce Réunions
pixel pixel puce Statuts

L’entreprise
pixel
pixel pixel L’ensemble des articles relatifs à l’entreprise Easter-eggs
pixel
pixel pixel puce Assemblées générales
pixel pixel puce Comptabilité
pixel pixel puce Fonctionnement
pixel pixel puce Statuts

Logiciels Libres
pixel pixel puce Histoire, Philosophie
pixel pixel puce Nos contributions
pixel pixel puce Trucs et astuces
pixel pixel puce Tutoriaux



logo GNU

logo debian

Tux, logo du noyeau linux

pixel
Assembleur x86, 1ère partie

vendredi 5 avril 2002, par Emmanuel Saracco


Cette série d’articles consacrés au langage d’assemblage pour processeurs x86 sous linux s’adresse à des débutants ayant quelques notions de programmation et ne se veut en aucun cas exhaustive.

Une version DocBook/HTML intégrant tous les articles présentés ici est disponible sur people.easter-eggs.org

Ceux d’entre vous ayant déjà codé en assembleur [1] sous DOS ou windows seront certainements surpris d’apprendre que la syntaxe qu’ils avaient employée jusqu’à présent n’est pas la seule disponible. En effet, il existe en fait deux styles de notation possibles :

Les conventions Intel

Ces conventions viennent directement du constructeur de microprocesseur ; c’est pourquoi elles sont suivies par la majeure partie des assembleurs modernes. Le code généré est clair et épuré.

Exemple

push ebp
mov ebp,esp
push ebx
push esi
push edi

Les conventions AT&T

Ce style de codage est né en même temps qu’Unix et les conventions datent donc de cette époque. Il est un peu perturbant si l’on a pris l’habitude de coder en suivant les conventions Intel, mais on se familiarise assez rapidement avec.

Exemple

pushl %ebp
movl %esp,%ebp
pushl %ebx
pushl %esi
pushl %edi

Il existe quelques assembleurs qui permettent d’utiliser les conventions Intel sur de l’Unix, le plus abouti étant Nasm. Dans cette suite d’articles nous utiliserons les conventions de notation Intel et emploierons Nasm pour les raisons suivantes :

-  La convention Intel nous semble être plus claire et moins source d’erreurs que la convention AT&T.
-  Nasm permet à ceux qui étaient habitués à coder sous DOS de garder leurs habitudes :-)

A vrai dire, deux bonnes raisons qui auraient pu nous faire pencher pour l’utilisation des conventions AT&T sont :

-  Le format d’affichage de GNU gdb.
-  La syntaxe de l’assembleur inline dans du code C via __asm__().

Néanmoins, nous adressant ici à des débutants en assembleur il ne fallait pas compliquer les choses [2]

Qu’est-ce que c’est ?

Vous avez sûrement déjà codé avec un langage de haut niveau comme C ou Pascal. Ces langages permettent d’écrire de manière quasi naturelle ce que nous voulons que la machine fasse : un programme C exécutant : « afficher "coucou" » s’écrira [3] :

Exemple coucou_c.c

void main()
{
 puts("coucou\n");
}

La même chose en assembleur s’écrirait [4] :

Exemple coucou_asm.asm

section        .text
        global        _start

msg        db        'coucou',0x0A
msg_len        equ        $ - msg

_start:
        mov        eax,4
        mov        ebx,1
        mov        ecx,msg
        mov        edx,msg_len
        int        0x80

        mov        eax,1
        int        0x80

Ce dernier source est tout à fait fonctionnel et autonome. Nous aurions pu également nous aider de la libc et éviter la manipulation directe de l’interruption 0x80, et nous aurions alors eu le mélange de C et d’assembleur suivant [5] :

Exemple coucou_asm_libc.asm

extern puts
       
section        .text
        global        main

msg        db        'coucou',0

main:
        push        ebp
        mov        ebp,esp
        push        ebx
        push        esi
        push        edi

        push dword msg
        call        puts
       
        pop        edi
        pop        esi
        mov        esp,ebp
        pop        ebp
        ret

Lier son code assembleur avec la libc peut-être effectivement très pratique si l’on ne veut pas réinventer la roue ; mais il faut à ce moment se poser la question de savoir si nous n’aurions pas plus vite fait d’intégrer de l’assembleur inline dans un code C.

Dans le cadre d’applications « professionnelles » il est néanmoins conseillé de ne pas passer directement par l’interruption logicielle 0x80 pour faire appel aux routinex kernel. En effet, rien ne certifie que les services proposés par cette interruption ne changeront pas — l’équipe de développement kernel conseillant de toujours passer par la libc s’agissant des appels systèmes et se réservant le droit de modifier quoi que ce soit sans crier gare. Pour en savoir plus sur l’interruption 0x80 et les différents appels systèmes.

Malgré tout il existe quelques avantages à coder en assembleur « pur » (c’est à dire, à ne pas se lier avec la libc) :

-  La vitesse d’exécution.
-  La taille du code généré.
-  Le faible besoin en RAM.

Pour ce qui est de la vitesse d’exécution, il est vrai qu’on arrive rapidement à produire un code moins performant que celui généré par gcc, mais tout dépend de ce qu’on fait de ce pour quoi on utilise l’assembleur. Dans la majeure partie des cas la nécessité d’écrire un programme entier en assembleur ne se posera pas — s’il s’agit d’optimisation, on emploiera plus volontier de l’assembleur inline.

Mais si, par exemple, il est vital d’obtenir un binaire très petit, si la RAM disponible est très faible ou encore si l’on ne veut absolument pas se lier avec une librairie comme la libc, alors on pourra se fier à l’assembleur. Quelques explications supplémentaires pourront être trouvées sur Linuxego.

Voici en guise d’exemple un tableau récapitulant les différents programmes sourcés ci-dessus et la taille des binaires générés (avant et après un strip [6]) :

Nom Taille Strip
coucou_asm 428 428
coucou_asm_libc 4751 2956
coucou_c 4792 3000

On voit que c’est sans conteste le programme écrit en assembleur qui l’emporte au niveau de la taille finale [7].

SUITE de cet article


[1] L’expression exacte serait « langage d’assemblage », l’assembleur étant le programme qui permet de transformer le langage d’assemblage en code binaire ; néanmoins, nous emploierons ici le terme « assembleur » pour nous simplifier la tâche.

[2] Nous envisagerons peut-être de faire quelques articles expliquant la convention AT&T par la suite — tout dépendra de la demande :-)

[3] Le code est volontairement dépouillé du superflu. Utilisez gcc coucou_c.c -o coucou_c pour compiler cet exemple.

[4] Utilisez nasm -f elf coucou.asm; ld -s coucou_asm.o -o coucou_asm pour compiler cet exemple.

[5] Utilisez nasm -f elf coucou_asm_libc.asm; gcc coucou_asm_libc.o -o coucou_libc pour compiler cet exemple.

[6] Utilisez strip -s mon_prog. Stripper un programme consiste à l’alléger en supprimant les symboles qu’il contient.

[7] Pour vous détendre un peu et voir jusqu’ou on peut aller pour faire maigrir un code, jetez un oeil sur A Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux


pixel pixel pixel

Dans la même rubrique :
puce Assembleur x86, 1ère partie (suite)
puce Assembleur x86, 2ème partie
puce Assembleur x86, 2ème partie (suite)
puce Assembleur x86, 3ème partie
puce Assembleur x86, 3ème partie (suite)
puce Comment créer de la musique avec GNU/Linux
puce Guide simplifié pour QEMU
puce Introduction à LDAP

pixel
pixel
pixel


Proposer un article | Nous contacter | Plan du site | Admin | Accueil



Fatal error: Cannot redeclare spip_connect_ldap() (previously declared in /var/www/eeweb/eeorg/public_html/ecrire/inc_connect.php3:9) in /var/www/eeweb/eeorg/public_html/ecrire/inc_connect.php3 on line 12