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, 2ème 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, 2ème partie

mardi 9 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


-  Assembleur x86, 1ère partie

Dans notre premier article nous avions laissé de côté la description des registres du processeur et leur rôle respectif. Nous allons ici rapidement aborder le sujet — juste assez pour pouvoir nous débrouiller par la suite.

Tout d’abord, précisons que sous GNU/Linux, contrairement à ce qui se passait sous DOS, nous n’avons pas vraiment besoin de nous encombrer avec la notion de « segment ». En effet, bien que les segments soient évidemment présents, leur taille peut aller jusqu’à 4Go... Donc, nous n’aurons plus à jouer avec cs, ds et es constamment :-) Penchons-nous plutôt sur ce qui nous touche de près : les registres du microprocesseur. Les registres qui nous intéressent particulièrement sont :

-  Les registres de travail : eax, ebx, ecx et edx.
-  Les registres d’offset : esi, edi, ebp et esp.
-  Le registre des flags : eflags.

Les registres de travail

Comme nous l’indiquions brièvement dans le premier article, ces registres (sur 32 bits depuis le 80386) peuvent être décomposés en plusieurs sous-registres. Vous serez sûrement surpris de constater qu’on ne peut atteindre directement les 16 bits de poids fort des registres e*x, et que les registres *x ne représentent que les 16 bits de poids faible [1]. Si cela vous dérange, vous pourrez toujours utiliser l’instruction movzx qui permet d’étendre *x dans e*x.

Registre(s)Taille
eax32 bits
ax16 bits
ahal8 bits chacun

On voit que e*x (32 bits) est composé de *x (16 bits de poids faible) lui-même composé de *h (8 bits de poids fort) et *l (8 bits de poids faible).

Registre Nom Description
eax Accumulateur Sert aux opérations mathématiques mais aussi à la transmission des numéros de fonctions à appeler lorsqu’on se sert de l’interruption système 0x80 et au renvoi des résultats dans les fonctions (que nous aborderons dans un prochain article).
Lorsque vous devez utiliser un registre pour une opération quelconque et que vous ne savez pas lequel utiliser, privilégiez celui-ci — c’est le plus optimisé au niveau de la rapidité d’exécution des opérations.
ebx Base Utilisé pour l’adressage indirect
ecx Compteur Ce registre est utilisé chaque fois que l’assembleur a besoin d’un « compteur ». Nous devrons l’utiliser lorsque nous mettrons en place des boucles via l’instruction loop ou encore lorsque nous ferons des transferts de données entre esi et edi.
edx Données Sert aussi pour quelques opérations mathématiques.

Même si chacun de ces registres est optimisé ou utilisé pour certaines opérations, ils peuvent être employés à toutes fins utiles. Il suffit juste de savoir, par exemple, que c’est le registre ecx et lui seul qui sera utilisé et décrémenté par l’instruction movsd dans le cas de la copie d’une chaîne [2]. Cela ne veut pas dire que ecx est dédié à cette tâche de « compteur », mais juste qu’il est optimisé par le processeur pour cette tâche et utilisé en tant que tel par d’autres instructions.

Les registres d’offset

Registre Nom Description
esi Source Index Utilisé lors des opérations sur les chaînes de caractères
edi Destination Index Comme esi, ce registre sert lors des opérations sur des chaînes de caractères.
ebp Base Pointer Référence la base de la pile
eip Instruction Pointer Ce registre est particulier car il ne peut pas être manipulé directement. Il pointe en permanence sur la prochaine opération à exécuter.
esp Stack Pointer Pointe vers le dernier élément déposé sur la pile (l’élément courant)

Le registre des flags

eflags est un registre 32 bits qui rend compte de l’état du processeur après chaque instruction. Il est composé du sous-registre flags (16 bits de poids faible). On n’accède jamais à ce registre dans son intégralité, mais toujours bit par bit lorsqu’on veut une information bien précise sur, par exemple, le résultat d’une comparaison ou d’une opération arithmétique. Les drapeaux les plus importants pour nous sont les suivants :

Drapeau Nom Position
cf Carry Flag 0
pf Parity Flag 2
af Auxiliary Carry Flag 4
zf Zero Flag 6
sf Sign Flag 8
if Interruption Flag 9
df Direction Flag 10
of Overflow Flag 11

Il en existe d’autres, mais nous ne les utiliserons pas ici.

Les structures de contrôle

On peut bien sûr produire en assembleur le même genre de boucle que dans un langage de haut niveau. Nous verrons à cette occasion l’utilité des registres eflags et ecx.

Boucle WHILE

Le test est fait en début de boucle.

Code C Assembleur

compteur = 0;
while ( compteur < 10)
        ++compteur;

        xor ax,ax
debut:
        cmp ax,10
        jae fin
        inc ax
        jmp debut
fin:       


L’instruction jae nous permet ici de tester si le terme gauche de la comparaison faite avec cmp est supérieur ou égal au terme de droite. Dès que ax est supérieur ou égale à 10 alors on saute au label fin, sinon, on incrémente ax et on saute impérativement au label debut. jae vérifie la valeur du flag CF. Si CF=0, alors la condition est remplie.

Boucle DO..WHILE

Le test est fait en fin de boucle.

Code C Assembleur

compteur = 0;
do
        ++compteur;
while (compteur < 10);

        xor ax,ax
debut:
        inc ax
        cmp ax,10
        jb debut

L’instruction jb nous permet ici de tester si le terme gauche de la comparaison faite avec cmp est inférieur au terme de droite. Tant que ax est inférieur à 10 alors on saute au label debut. jb vérifie la valeur du flag CF. Si CF=1, alors la condition est remplie.

Boucle FOR

Aucun test n’est fait. On effectue un nombre determiné d’itérations.

Code C Assembleur

int compteur;
for (
        compteur = 0;
        compteur < 10;
        compteur++
) ;

        mov ecx,10
debut:
        nop
        loop debut

La boucle for n’étant en fin de compte qu’une variante de while il existe bien sûr plusieurs façons de faire. Ici, nous nous servons du registre compteur ecx. Nous avons un bel exemple d’instruction loop qui s’attend à trouver dans ecx le nombre d’itérations à accomplir et qui décrémente automatiquement ce registre.

SUITE de cet article


[1] On désigne par « bits de poids faible » les bits situés le plus à droite, et « bits de poid fort » ceux situés le plus a gauche. Par exemple, si nous travaillons avec un registre de 16 bits et que nous y mettons la valeur hexadécimale 0x4d50 : mov ax,4d50h, al contiendra 0x50 et ah contiendra 0x4d.

[2] nous aborderons cet exemple plus loin lorsque nous parlerons des boucles.


Assembleur x86, 2ème partie
14 novembre 2006, par Jacqueline

Super article..

J’ai travaillé pendant vingt cinq ans dans l’informatique industrielle temps réel, où pour des raisons de coûts, de technologie et surtout de vitesse d’éxécution on écrit les programmes en assembleur.. mais avant , je travaillais dans l’électronique numérique . sur le premier calculo, l’additionneur, c’était un rack avec des cartes équipées de SN7400 ( quatre portes NAND )

C’est fou ce qu’on peut faire avec des programmes de moins de 32 k.. On conduit des processus industriels entiers, avec de la régulation PID, des mesures, du filtrage, des asservissements, de la télécommande et de la télémesure à distance..avec des protocoles évolués..

Bien évidemment à chaque changement de bécane, il faut se reconvertir, les programmes ne sont pas portables, mais on s’y fait très vite..

En assembleur on est pas à la merci d’un compilateur et de ses bibliothèques plus ou moins bien adaptées.. J’en ai fait l’expérience avec un compilateur Fortan après un changement de version du système de développement pour des applis non temps réel.

L’OS n’est pas multiplateforme, il est plus adapté à la bécane et donc plus simple..

En cas de panne ( plantage ) on ne sait pas toujours si celà provient d’un pb hard ou d’un problème soft et on pouvait utiliser les outils de déboggage de la machine.. Idem pour écrire des progs de test du métériel, trop cher pour le jeter..Et sur place , bouit de programme assemblé à la main et rentré aux clés sur le pupitre.

Aujourd’hui je ne me risquerais pas d’écrire un prog en assembleur pour les nouveaux processeurs, il faut déjà un millier de lignes pour initialiser correctement le processeur..

Avec les "pipe" , il faut faire très attention à la vitesse des instructions et les mettre dans le bon ordre, il faut gérer l’hyperthreading et les caches .. chapeau tout de même aux gens qui ont conçu ces nouveaux processeurs et à ceux qui écrivent les compilateurs.. mais je préfère un processeur RISC avec moins d’instructions et en 64 bits..on gagne du temps..

Sans parler du BIOS qui reste tout de même mystérieux et compliqué...

J’aime toujours beaucoup l’assembleur, et il n’y a pas très longtemps, j’ai découvert les "micromodules" avec des processeurs très simples ( de la famille de 8080, 6500 et 68000, qui ont retrouvé une nouvelle jeunesse ( ils représentent une part très importante du marché des processeurs tous confondus.. Ces cartes aujourd’hui possèdent de nombreux interfaces : Ethernet, USB, COM , TOR, entrées analogiques..cartes flash , bluetooth et autres..

Les plus évoluées fonctionnent avec des OS comme Microlinux, plus une couche temps réel, mais je pense que j’aurais plus vite fait de réécrire un OS adapté au problème à gérer que comprendre comment fonctionne un Microlinux et d’adapter les paquetages dont j’aurais besoin pour gérer telle ou telle interface..

La capacité mémoire n’étant pas illimitée, mais suffisante, il n’est pas envisageable d’écrire le programme en C++, mais en est-il besoin.. ? Souvent ce n’est que parce que les gens ne connaissent que les langages évolués..

Cette découverte m’a montré que l’assembleur n’était pas mort, bien au contraire.. et ces micromodules sont bien plus ouverts au niveau des utilisations ( robotique, domotique et intégration dans les équipements électroniques qu’ils ont beaucoup simplifié ) que ne l’est un PC, plus tourné vers la bureautique, le calcul scientifique, le multimédia et le dévelopement.

Autre intéret : une carte 68H11 basique coûte une trentaine d’euros, les plus évoluées comme la Cobra coûtent dans les 300 euros.. de quoi bien s’amuser..

En 8086, je n’ai pas encore trouvé de carte et je me désespérais de trouver un assembleur.. Paraît il que c’était dépassé..

Le PC ne sert plus alors que de plateforme de dévelopement , ce qui coûtait une fortune à l’époque où sont sortis ces premiers processeurs, et donc interdisait leur emploi à usage personnel.. mais je me suis bien vengée avec l’Apple II et un kit de dévelopement en assembleur..

Avec mon PC, je suis très frustrée.. déjà par la multiplicité des langages. Il faut se tapper la doc de QT designer et de Kdevelop..il manque toujours une librairie ou ce n’est pas la bonne version, j’aurais largement eu le temps d’écrire mon prog en assembleur..

En assembleur on structure aussi bien ses programmes, on est sur de l’allocation mémoire, on écrit pas d’instruction inutile..

Il existe aussi l’assemblage optionnel qui permet de n’avoir qu’un seul source et de l’adapter à diverses configutations matérielle, plus l’édition de lien qui permet de découper un gros programme en modules des modules réutilisables. L’assembleur n’est donc pas un truc ringard et aussi rustique qu’on l’entend..

La portabilité des langages évolués n’est pas toujours aussi évidente.. J’ai un Athlon 64 et tout ne marche pas correctement.. Sans parler des dépendances de paquetages, de l’utilisation de paquetages sur d’autres kernel... etc... Ce qui occupe presque à temps complet la plupart des linuxiens, au détriment de la programmation d’applications un peu innovantes.. A part les sites Web, qui se ressemblent de plus en plus..

Si j’écris un prog en langage évolué qui utilise telle librairie, rien est moins sur que demain je disposerais de cette librairie là..

Donc tout n’est pas rose avec les langages évolués....

Ecrire en assembleur assure une réelle indépendance, pour ne pas dire une certaine autonomie.

Dans Grub stage 1 et stage 2 sont écrits en assembleur 8086, ça se lit !Dommage que ça s’arrète là ..

Je poursuis ma lecture...

Merci pour cet article super bien fait qui restera dans mes favoris.

Jacqueline

Répondre à ce message

pixel pixel pixel

Dans la même rubrique :
puce Assembleur x86, 1ère partie
puce Assembleur x86, 1ère partie (suite)
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