Support de cours utiliser des structures en Assembleur, tutoriel & guide de travaux pratiques Assembleur en pdf.
Bases du Langage Assembleur
Travailler avec les Entiers
Représentation des entiers
Les entiers se dÈcomposent en deux catÈgories : signÈs et non signÈs. Les entiers non signÈs (qui sont positifs) sont reprÈsentÈs d’une maniËre binaire trËs intuitive. Les nombre 200 en tant qu’entier non signÈ sur un octet serait reprÈsentÈ par 11001000 (ou C8 en hexa).
Les entiers signÈs (qui peuvent Ítre positifs ou nÈgatifs) sont reprÈsentÈs d’uneprÈsentÈfaÁonpar plusl’octetcompliquÈe00111000..ParSurexemple,papier, onconsidÈronspeutreprÈsenter−56.+56 serait re-−56 comme −de111000l’ordinateur,mais. commentCommentcelaseraitseraitstockÈ-ilreprÈsentÈlesignemoinsdans ?un octet en mÈmoire
Il y a trois techniques principales qui ont ÈtÈ utilisÈes pour reprÈsenter les entiers signÈs dans la mÈmoire de l’ordinateur. Toutes ces mÈthodes utilisent le bit le plus signi catif de l’entier comme bit de signe. Ce bit vaut 0 si le nombre est positif et 1 s’il est nÈgatif.
Grandeur signée
La premiËre mÈthode est la plus simple, elle est appelÈe grandeur signÈe. Elle reprÈsente l’entier en deux parties. La premiËre partie est le bit de signe et la seconde est la grandeur entiËre. Donc 56 serait reprÈsentÈ par l’octet d00111000’octetla (leplusbitgrandedesigneseraitest soulignÈ) et −56 serait 10111000. La valeur sur un octet serait 01111111 soit +127 et la plus petite valeur on inverse le bit de1 1111111signe.Cettesoit mÈthode−127.Pourest obtenirintuitivel’opposÈmaisa d’unesesinconvÈvaleur,-
Voici une astuce utile pour trouver le complÈment ‡ un d’un nombre en hexadÈcimal sans repasser en binaire. L’astuce est d’Ùter le chi re hexa de F (ou 15 en dÈcimal). Cette mÈthode suppose que le nombre de bits dans le hexanombre.pourest trouvermultiplele decomplÈment4.Voiciun‡ un,exempleÙtez chaque:+56 chiest reprÈsentÈredeFpourparobtenir38en C7 en hexa. Cela concorde avec le rÈsultat ci-dessus.
Complément ‡ deux
Les deux premiËres mÈthodes dÈcrites ont ÈtÈ utilisÈes sur les premiers ordinateurs. Les ordinateurs modernes utilisent une troisiËme mÈthode ap-pelÈe reprÈsentation en complÈment ‡ deux. On trouve le e complÈment ‡ deux d’un nombre en e ectuant les deux opÈrations suivantes :
1. Trouver le complÈment ‡ un du nombre
2. Ajouter un au rÈsultat de l’Ètape 1
VoicicomplÈmentunexemple‡un :en utilisant 00111000 (56). Tout d’abord, on calcule le 11000111.
Extension de signe
En assembleur, toutes les donnÈes ont une taille bien spÈci Èe. Il n’est pas rare de devoir changer la taille d’une donnÈe pour l’utiliser avec d’autres. RÈduire la taille est le plus simple.
Réduire la taille des données
Pour rÈduire la taille d’une donnÈe, il su t d’en retirer les bits les plus signi catifs. Voici un exemple trivial :
mov
mov
ax, 0034h
cl, al
; ax = 52 (stockÈ sur 16 bits)
; cl = les 8 bits de poids faible de ax
Bien s˚r, si le nombre ne peut pas Ítre reprÈsentÈ correctement dans une plus petite taille, rÈduire la taille ne fonctionne pas. Par exemple, si AX valait 0134h (ou 308 en dÈcimal) alors le code ci-dessus mettrait quand mÍme CL ‡ 34h. Cette mÈthode fonctionne ‡ la fois avec les nombres signÈs et non signÈsalors. ConsidÈronsvaudraitFFhles (nombres signÈs, si AX valait FFFFh (−1 sur un mot), dans CL) Ètait signÈ, elle−aurait1sur un ÈtÈ octet )tronquÈ .Cependant, et le rÈsultat note zaurait que Èt Èsila faux valeur! AX
La rËgle pour les nombres non signÈs est que tous les bits retirÈs soient ‡ 0 a n que la convertion soit correcte. La rËgle pour les nombres signÈs est que les bits retirÈs doivent soit tous Ítre des 1 soit tous des 0. De plus, Le premier bit ‡ ne pas Ítre retirÈ doit valoir la mÍme chose que ceux qui l’ont ÈtÈ. Ce bit sera le bit de signe pour la valeur plus petite. Il est important qu’il ait la mÍme valeur que le bit de signe original !
Augmenter la taille des données
Augmenter la taille des donnÈes est plus compliquÈ que la rÈduire. Consi-dÈrons l’octet hexa FF. S’il est Ètendu ‡ un mot, quelle valeur aura-t-il ? Cela dÈpend de la faÁon dont FF est interprÈtÈ. Si FF est un octet non signÈ (255 en dÈcimal), alors le mot doit Ítre 00FF ; cependant, s’il s’agit d’un octet signÈ (−1 en dÈcimal), alors le mot doit Ítre FFFF.
En gÈnÈral, pour Ètendre un nombre non signÈ, on met tous les bits supplÈmentaires du nouveau nombre ‡ 0. Donc, FF devient 00FF. Cependant, pour Ètendre un nombre signÈ, on doit Ètendre le bit de signe. Cela signi e que les nouveaux bits deviennent des copies du bit de signe. Comme le bit
TRAVAILLER AVEC LES ENTIERS
33 de signe de FF est ‡ 1, les nouveaux bits doivent Ègalement Ítre des uns, pour donner FFFF. Si le nombre signÈ 5A (90 en dÈcimal) Ètait Ètendu, le rÈsultat serait 005A.
Il y a plusieurs instructions fournies par le 80386 pour Ètendre les nombres.
Souvenez vous que l’ordinateur ne sait pas si un nombre est signÈ ou non.
C’est au programmeur d’utiliser l’instruction adÈquate.
Pour les nombres non signÈs, on peut placer des 0 dans les bits de poids fort de faÁon simple en utilisant l’instruction MOV. Par axemple pour Ètendre l’octet de AL en un mot non signÈ dans AX :
mov ah, 0 ; met les 8 bits de poids for ‡ 0
Cependant, il n’est pas possible d’utiliser une instruction MOV pour convertir le mot non signÈ de AX en un double mot non signÈ dans EAX. Pourquoi pas ? Il n’y a aucune faÁon d’accÈder aux 16 bits de poids fort de EAX dans un MOV . Le 80386 rÈsoud ce problËme en fournissant une nouvelle ins-truction : MOVZX . Cette instruction a deux opÈrandes. La destination (pre-mier opÈrande) doit Ítre un registre de 16 ou 32 bits. La source (deuxiËme opÈrande) doit Ítre un registre 8 ou 16 bits. L’autre restriction est que la destination doit Ítre plus grande que la source (la plupart des instructions recquiËrent que la source soit de la mÍme taille que la destination).
1 Introduction
1.1 Systèmes Numériques
1.1.1 Décimal
1.1.2 Binaire
1.1.3 Hexadecimal
1.2 Organisation de l’Ordinateur
1.2.1 Mémoire
1.2.2 Le CPU (processeur)
1.2.3 La famille des processeurs 80×86
1.2.4 Regitres 16 bits du 8086
1.2.5 Registres 32 bits du 80386
1.2.6 Mode Réel
1.2.7 Mode Protégé 16 bits
1.2.8 Mode Protégé 32 bits
1.2.9 Interruptions
1.3 Langage Assembleur
1.3.1 Langage Machine
1.3.2 Langage d’Assembleur
1.3.3 Opérandes d’Instruction
1.3.4 Instructions de base
1.3.5 Directives
1.3.6 Entrées et Sorties
1.3.7 Débogage
1.4 Créer un Programme
1.4.1 Premier programme
1.4.2 Dépendance vis à vis du compilareur
1.4.3 Assembler le code
1.4.4 Compiler le code C
1.5 Fichier Squelette
2 Bases du Langage Assembleur
2.1 Travailler avec les Entiers
2.1.1 Représentation des entiers
2.1.2 Extension de signe
2.1.3 Arithmétique en complément à deux
2.1.4 Programme exemple
2.1.5 Arithmétique en précision étendue
2.2 Structures de Contrôle
2.2.1 Comparaison
2.2.2 Instructions de branchement
2.2.3 Les instructions de boucle
2.3 Traduire les Structures de Contrôle Standards
2.3.1 Instructions if
2.3.2 Boucles while
2.3.3 Boucles do while
2.4 Exemple : Trouver des Nombres Premiers
3 Opérations sur les Bits
3.1 Opérations de Décalage
3.1.1 Décalages logiques
3.1.2 Utilisation des décalages
3.1.3 Décalages arithmétiques
3.1.4 Décalages circulaires
3.1.5 Application simple
3.2 Opérations Booléennes Niveau Bit
3.2.1 L’opération ET
3.2.2 L’opération OU
3.2.3 L’opération XOR
3.2.4 L’opération NOT
3.2.5 L’instruction TEST
3.2.6 Utilisation des opérations sur les bits
3.3 Eviter les Branchements Conditionnels
3.4 Manipuler les bits en C
3.4.1 Les opérateurs niveau bit du C
3.4.2 Utiliser les opérateurs niveau bit en C
3.5 Représentations Big et Little Endian
3.5.1 Quand se Soucier du Caractère Big ou Little Endi
4 Sous-Programmes
4.1 Adressage Indirect
4.2 Exemple de Sous-Programme Simple
4.3 La pile
4.4 Les Instructions CALL et RET
4.5 Conventions d’Appel
4.5.1 Passer les paramètres via la pile
4.5.2 Variables locales sur la pile
4.6 Programme Multi-Modules
4.7 Interfacer de l’assembleur avec du C
4.7.1 Sauvegarder les registres
4.7.2 Etiquettes de fonctions
4.7.3 Passer des paramètres
4.7.4 Calculer les adresses des variables locales
4.7.5 Retourner des valeurs
4.7.6 Autres conventions d’appel
4.7.7 Exemples
4.7.8 Appeler des fonctions C depuis l’assembleur
4.8 Sous-Programmes Réentrants et Récursifs
4.8.1 Sous-programmes récursifs
4.8.2 Révision des types de stockage des variables en
5 Tableaux
5.1 Introduction
5.1.1 Dénir des tableaux
5.1.2 Accéder aux éléments de tableaux
5.1.3 Adressage indirect plus avancé
5.1.4 Exemple
5.1.5 Tableaux Multidimensionnels
5.2 Instructions de Tableaux/Chaînes
5.2.1 Lire et écrire en mémoire
5.2.2 Le préxe d’instruction REP
5.2.3 Instructions de comparaison de chaînes
5.2.4 Les préxes d’instruction REPx
5.2.5 Exemple
6 Virgule Flottante
6.1 Représentation en Virgule Flottante
6.1.1 Nombres binaires non entiers
6.1.2 Représentation en virgule ottante IEEE
6.2 Arithmétique en Virgule Flottante
6.2.1 Addition
6.2.2 Soustraction
6.2.3 Multiplication et division
6.2.4 Conséquences sur la programmation
6.3 Le Coprocesseur Arithmétique
6.3.1 Matériel
6.3.2 Instructions
6.3.3 Exemples
6.3.4 Formule quadratique
6.3.5 Lire un tableau depuis un chier
6.3.6 Renchercher les nombres premiers
7 Structures et C++
7.1 Structures
7.1.1 Introduction
7.1.2 Alignement en mémoire
7.1.3 Champs de Bits
7.1.4 Utiliser des structures en assembleur
7.2 Assembleur et C++
7.2.1 Surcharge et Décoration de Noms
7.2.2 Références
7.2.3 Fonctions inline
7.2.4 Classes
7.2.5 Héritage et Polymorphisme
7.2.6 Autres fonctionnalités C++