le forum de tous vos problèmes informatique

Résolution de problemes en informatique en tout genre
 
AccueilAccueil  FAQFAQ  RechercherRechercher  S'enregistrerS'enregistrer  MembresMembres  GroupesGroupes  ConnexionConnexion  

Partagez | 
 

 Langage assembleur!

Voir le sujet précédent Voir le sujet suivant Aller en bas 
AuteurMessage
Momo
Caporal-chef


Nombre de messages : 120
Localisation : St Etienne
Date d'inscription : 16/01/2005

MessageSujet: Langage assembleur!   Sam 22 Jan à 10:22

Les prérequis nécessaires


Le langage assembleur est très proche du langage machine (c'est-à-dire le langage qu'utilise l'ordinateur: des informations binaires, soit des 0 et des 1). Il dépend donc fortement du type de processeur. Ainsi il n'existe pas un langage assembleur, mais un langage assembleur par type de processeur. Il est donc nécessaire de connaître un minimum le fonctionnement d'un processeur pour pouvoir aborder cette partie. Un processeur réel a toutefois trop de registres et d'instructions pour pouvoir les étudier en détail. C'est pour cette raison que seuls les registres et les instructions d'un processeur simple (Intel 80x86 16 bits) seront étudiés dans ce dossier.

Le processeur en bref...


Un processeur est relié à la mémoire par l'intermédiaire d'une liaison appelée bus. Les données dont le processeur a besoin sont stockées dans ce que l'on appelle des registres (ils sont notés AX, BX, CX, DX, ...). Chacun a sa propre utilité:

Nom du registre Taille
Accumulateur AX 16 bits
Registre auxiliaire de base BX 16 bits
Registre auxiliaire (compteur) CX 16 bits
Registre auxiliaire de données DX 16 bits
Pointeur d'instruction IP 16 bits
Index de source SI 16 bits
Index de destination DI 16 bits
Registre segment de code CS 16 bits
Registre segment de données DS 16 bits
Registre segment de pile SS 16 bits
Registre segment supplémentaire ES 16 bits
Pointeur de pile SP 16 bits
Pointeur de base BP 16 bits


Les registres AX, BX, CX et DX sont les registres les plus utilisés pour les calculs :

Le registre AX sert à effectuer des calculs arithmétiques ou à envoyer un paramètre à une interruption
Le registre BX sert à effectuer des calculs arithmétiques ou bien des calculs sur les adresses
Le registre CX sert généralement comme compteur dans des boucles
Le registre DX sert à stocker des données destinées à des fonctions
Il s'agit là de l'utilisation de base de ces registres, mais dans la pratique ils peuvent être utilisés à d'autres fins.
Les registres AX, BX, CX et DX peuvent être utilisés par bloc d'un octet (8 bits), la lettre X de leur nom est alors remplacé par L (comme Low pour désigner les bits de poids faible) et H (pour High afin de désigner les bits de poids forts). De plus, dans les architectures x86 32 bits, ces registres ont été étendus à 32 et ont vus leur nom précédé d'un E (pour Extended, en français "étendu").

EAX (32 bits)
AX (16 bits)
AH (8 bits) AL (8 bits)


Pourquoi utiliser l'assembleur?


Pour faire exécuter une suite d'instructions au processeur, il faut lui fournir des données binaires (souvent représentées en notation hexadécimale pour plus de lisibilité, mais cela revient au même...). Or, les fonctions en notation hexadécimale sont difficiles à retenir, c'est pourquoi le langage assembleur a été mis au point. Il permet de noter les instructions avec des noms explicites suivis de paramètres.

Voici par exemple à quoi peut ressembler un programme en langage machine:
A1 01 10 03 06 01 12 A3 01 14

Il s'agit de la représentation hexadécimale d'un programme permettant d'additionner les valeurs de deux cases mémoire et de stocker le résultat dans une troisième case. Il est évident que ce type d'écriture est difficilement lisible par nous, humains.

Ainsi, puisque toutes les instructions que le processeur peut effectuer sont associées à une valeur binaire chacune, on utilise une notation symbolique sous forme textuelle qui correspond à chaque fonction, c'est ce que l'on appelle le langage assembleur. Dans l'exemple précédent la séquence A1 01 10 signifie copier le contenu de la mémoire à l'adresse 0110h dans le registre AX du processeur. Cela se note en langage assembleur:
MOV AX, [0110]

Toutes les instructions ont une notation symbolique associée (fournie par le fabricant du processeur). L'utilisation du langage assembleur consiste donc à écrire sous forme symbolique la succession d'instructions (précédées de leur adresse pour pouvoir repérer les instructions et passer facilement de l'une à l'autre). Ces instructions sont stockées dans un fichier texte (le fichier source) qui, grâce à un programme spécifique (appelé "l'assembleur") sera traduit en langage machine.

Le programme précédent écrit en langage assembleur donnerait:

Adresse de l'instruction Instruction en langage machine Instruction en langage assembleur Commentaires sur l'instruction
0100 A1 01 10 MOV AX, [0110] Copier le contenu de 0110 dans le registre AX
0103 03 06 01 12 ADD AX, [0112] Ajouter le contenu de 0112 à AX et mettre le résultat dans AX
0107 A3 01 14 MOV [0114], AX Stocker AX à l'adresse mémoire 0114


L'écriture en langage assembleur, bien que restant rebutante, est beaucoup plus compréhensible pour un humain, car on a généralement moins de mal à retenir un nom qu'un numéro...

Ce document intitulé «L'assembleur - Introduction» issu de CommentCaMarche.net est soumis à la licence GNU FDL. Vous pouvez copier, modifier des copies de cette page tant que cette note apparaît clairement.


Dernière édition par le Sam 22 Jan à 10:34, édité 1 fois
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://jassomo.club.fr/index.htm
Momo
Caporal-chef


Nombre de messages : 120
Localisation : St Etienne
Date d'inscription : 16/01/2005

MessageSujet: Re: Langage assembleur!   Sam 22 Jan à 10:24

La compilation du programme


Le programme doit être saisi dans un fichier texte non formatté (c'est-à-dire sans caractères en gras, souligné, avec des polices de caractères de différentes tailles, ...) appelé fichier source. En effet, l'assembleur (le programme permettant de faire la traduction du langage assembleur en langage machine) permet uniquement de créer un fichier assemblé à partir du fichier source (il devra comporter l'extension .ASM, en s'appelant par exemple source.asm ou n'importe quel autre nom suivi de l'extension .asm).

L'assembleur va fournir un fichier objet (dont l'extension est .obj) qui va contenir l'ensemble des instructions traduites en instructions machines. Ce fichier .OBJ ne pourra toutefois pas s'exécuter directement car il faut encore lier les différents fichiers.
Comment ça les différents fichiers?
En effet il est possible de construire un exécutable à partir de plusieurs fichiers sources (à partir d'un certain niveau de programmation il devient intéressant de créer des fichiers contenant des fonctions...). Ainsi, même si vous avez un seul fichier objet il vous faudra utiliser un programme (appelé éditeur de liens) qui va vous permettre de créer un fichier exécutable (dont l'extension sera ".exe").

Note d'un visiteur :
Les fichiers de sortie ne sont pas obligatoirement des fichiers object, ni même un exécutable !
Il est en effet possible de générer un fichier binaire ne comportant que la traduction exacte du fichier source. Ce fichier binaire pourra par exemple être utilisé comme programme d'amorçage (boot) d'un ordinateur lorsqu'il sera placé sur le secteur d'amorçage (MBR) d'une disquette ou d'un disque dur.



A quoi ressemble un fichier source en assembleur?


Comme dans tout programme le fichier source doit être saisi de manière rigoureuse. Chaque définition et chaque instruction doivent ainsi s'écrire sur une nouvelle ligne (pour que l'assembleur puisse différencier les différentes intructions) Le fichier source contient:

Des définitions de données déclarées par des directives (mots spéciaux interprétés par l'assembleur, nous les étudierons plus tard, le but est ici de donner une idée de ce à quoi ressemble un fichier source) Celles-ci sont regroupées dans le segment de données délimité par les directives SEGMENT et ENDS
Puis sont placées les instructions (qui sont en quelque sorte le coeur du programme), la première devant être précédée d'une étiquette, c'est-à-dire par un nom qu'on lui donne. Celles-ci sont regroupées dans le segment d'instructions délimité par les directives SEGMENT et ENDS
Enfin le fichier doit être terminé par la directive END suivi du nom de l'étiquette de la première instruction (pour permettre au compilateur de connaître la première instruction à exécuter
(Les points-virgules marquent le début des commentaires, c'est-à-dire que tous les caractères situés à droite d'un point virgule seront ignorés)
Voici à quoi ressemble un fichier source (fichier .ASM):


donnees SEGMENT; voici le segment de données dont l'étiquette est donnees



;Placez ici les déclarations de données



donnees ENDS; ici se termine le segment de donnees







ASSUME DS:donnee, CS: instr







instr SEGMENT; voici le segment d'instructions dont l'etiquette est instr



debut:
;placez ici votre premiere instruction (son etiquette est nommée debut)


;Placez ici vos instructions



instr ENDS; fin du segment d'instructions







END debut; fin du programme suivie de l'etiquette de la premiere instruction






La declaration d'un segment


Comme nous le verrons plus loin, les données sont regroupées dans une zone de la mémoire appelé segment de données, tandis que les instructions se situent dans un segment d'instructions.

Le registre DS (Data Segment) contient le segment de données, tandis que le registre CS (Code Segment) contient le segment d'instructions. C'est la directive ASSUME qui permet d'indiquer à l'assembleur où se situe le segment de données et le segment de code.
Puis il s'agit d'initialiser le segment de données:


MOV AX, nom_du_segment_de_donnees

MOV DS, AX

Ce document intitulé «L'assembleur - Fichier source et compilation» issu de CommentCaMarche.net est soumis à la licence GNU FDL. Vous pouvez copier, modifier des copies de cette page tant que cette note apparaît clairement.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://jassomo.club.fr/index.htm
Momo
Caporal-chef


Nombre de messages : 120
Localisation : St Etienne
Date d'inscription : 16/01/2005

MessageSujet: Re: Langage assembleur!   Sam 22 Jan à 10:25

A quoi ressemble une instruction?


L'instruction est l'élément clé de l'ordinateur car c'est elle qui permet de spécifier au processeur l'action à effectuer. Toutes les instructions sont stockées en mémoire et un compteur dans le processeur permet de passer de l'une à l'autre.
Une instruction est composée de deux éléments:

le code opération: action à effectuer par le processeur
le champ opérande: donnée ou bien adresse de la case mémoire contenant une donnée
La taille d'une instruction dépend de l'instruction et de l'opérande, elle est généralement de quelques octets (1 à Cool. La taille des insructions dépend également de l'architecture du processeur. Elle peut ainsi atteindre 4 octets dans le cas de processeurs 32 bits, voir 8 octets pour les processeurs x86 64 bits. L'octet est l'unité qui est utilisée généralement car elle est pratique pour le stockage de certaines données (notamment les caractères).

code opération champ opérande


Les types d'instructions


L'ensemble des instructions est appelé jeu d'instruction. On peut les répartir selon plusieurs catégories selon le type d'action que son exécution déclenche.

Instructions d'affectation


Les instructions d'affectations permettent de faire des transferts de données entre les registres et la mémoire, c'est-à-dire:

soit une écriture (du registre vers la mémoire)
soit une lecture (de la mémoire vers un registre)
Instructions arithmétiques et logiques


Ce type d'instructions porte sur le registre AX (l'accumulateur). Elle permettent d'effectuer une opération entre le registre AX et une donnée puis stocker le résultat dans AX. Ces instructions sont:

l'addition: AX = AX + donnée
la soustraction: AX = AX - donnée
incrémentation: AX = AX + 1
décrémentation: AX = AX - 1
décalage à gauche
décalage à droite
Instructions de comparaison


Permet de comparer le registre AX à une donnée. Le résultat de la comparaison est indiquée grâce à ... des indicateurs...
Ces instructions (ainsi que les instructions de branchements) sont nécessaires pour permettre une "interactivité", c'est-à-dire qu'en fonction de certains paramètres le programme va pouvoir avoir divers comportement. Sans ces indicateurs les programmes auraient un comportement déterminé et le programme ferait constamment les mêmes actions (comme un film ...).

Instructions de branchement


Ce type d'instruction permet de sauter à une instruction non consécutive à l'instruction en cours. En l'absence de ce type d'instruction le processeur passe automatiquement à l'instruction suivante (c'est-à-dire l'instruction contiguë (en mémoire) à l'instruction en cours). C'est le registre IP qui repère l'instruction suivante à exécuter. Les instructions de branchement permettent donc de modifier la valeur de ce registre et ainsi de choisir la prochaine instruction à exécuter.

On distingue deux sortes de branchements:

Les branchements conditionnels: en fonction d'une condition à satisfaire le processeur traitera le branchement indiqué ou l'instruction suivante.
condition satisfaite: exécution de l'instruction située à l'adresse indiquée
condition non satisfaite: exécution de l'instruction suivante
Les branchements conditionnels sont très utiles, notamment pour créer des boucles ou des structures conditionnelles.
Les branchements inconditionnels: on affecte une valeur définie au registre IP, c'est-à-dire que l'on ira exécuter l'instruction vers laquelle il pointe après celle en cours quoi qu'il arrive!

Ce document intitulé «L'assembleur - Instructions» issu de CommentCaMarche.net est soumis à la licence GNU FDL. Vous pouvez copier, modifier des copies de cette page tant que cette note apparaît clairement.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://jassomo.club.fr/index.htm
Momo
Caporal-chef


Nombre de messages : 120
Localisation : St Etienne
Date d'inscription : 16/01/2005

MessageSujet: Re: Langage assembleur!   Sam 22 Jan à 10:27

On appelle "mode d'adressage" la manière dont la donnée est spécifiée dans une instruction. Selon le mode d'adressage la taille de l'instruction peut varier de 1 à 4 octets.

Il existe 5 modes d'adressage:

le mode d'adressage implicite
le mode d'adressage immédiat
le mode d'adressage relatif
le mode d'adressage direct
le mode d'adressage indirect
Le mode d'adressage implicite


Le mode d'adressage implicite correspond à une instruction ne comportant pas d'opérande. L'instruction est composée du code opération uniquement et sa taille peut varier entre 1 octet et 2 octets selon l'opération.

code opération (1 ou 2 octets)


Ce type d'instruction porte généralement sur des registres. Les opérations d'incrémentation ou de décrémentation d'un registre ont un mode d'adressage implicite.

Le mode d'adressage immédiat


On parle de mode d'adressage immédiat lorsque le code opérande contient une donnée. La taille de la donnée peut varier entre 1 et 2 octets.

code opération (1 ou 2 octets) code opérande (1 ou 2 octets)


Ce type d'instruction met en jeu un registre et une valeur (qu'il s'agisse d'une affectation, une addition, une soustraction ou bien même une comparaison), la taille de l'opérande dépendra donc du type de registre mis en jeu (1 octet pour un regsitre 8 bits, 2 pour un registre de 16 bits).
Dans le cas de l'instruction MOV BX, 8 l'opérande 8 sera codée sur 16 bits puisqu'il faut l'affecter à un registre 16 bits (BX).

Le mode d'adressage relatif


Ce type de mode d'adressage met en jeu un champ opérande contenant un entier relatif (sa taille est donc un octet).

code opération (1 octet) code opérande (1 octet)
On l'utilise pour les opérations de saut, l'entier relatif est appelé déplacement, il correspond à la longueur du saut que le processeur doit effectuer dans les instructions.

Le mode d'adressage direct


Le code opérande d'une instruction en mode d'adressage direct, contrairement au mode d'adressage immédiat, contient l'adresse d'une donnée en mémoire (au lieu de contenir la donnée). Une adresse étant codée sur 16 bits, la taille du champ opérande est donc de 2 octets.

code opération (1 ou 2 octets) code opérande (2 octets)


Il peut s'agir par exemple de l'affectation à un registre d'une donnée contenue dans une case mémoire. Ce mode d'adressage provoque un temps d'exécution de l'instruction plus long car l'accès à la mémoire principale est plus long que l'accès à un registre.

Le mode d'adressage indirect


Le mode d'adressage indirect permet d'accéder à une donnée par l'intermédiaire d'un registre (le registre BX) qui contient son adresse. Son utilité n'est pas apparente à ce stade, mais l'adressage indirect est très utile lors de l'utilisation de tableaux (parcours des cases d'un tableau) car il suffit d'incrémenter BX de la taille d'une case pour passer d'une case à une autre...

En adressage directe, on affecte directement au registre accumulateur (AX) l'adresse d'une donnée
MOX AX, [110]

En adressage indirect, on affecte à AX l'adresse contenue dans le registre BX
MOV AX, [BX]

La notion d'adressage indirect sera mieux développée

Ce document intitulé «L'assembleur - Les modes d'adressage» issu de CommentCaMarche.net est soumis à la licence GNU FDL. Vous pouvez copier, modifier des copies de cette page tant que cette note apparaît clairement.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://jassomo.club.fr/index.htm
Momo
Caporal-chef


Nombre de messages : 120
Localisation : St Etienne
Date d'inscription : 16/01/2005

MessageSujet: Re: Langage assembleur!   Sam 22 Jan à 10:28

Les instructions arithmétiques et logiques sont effectuées par l'unité arithmétique et logique. Il s'agit d'opération directement effectuées sur les bits de la donnée que l'on traite.

Sont comprises dans cette appellations:

les instructions d'addition
les instructions de soustraction
les instructions de décalage
les instructions de rotation
les instructions logiques (ET, OU, ...)
Les opérations arithmétiques et logiques modifient l'état des indicateurs.

Instructions d'addition


Les opérations arithmétiques se font de la même façon en binaire qu'en base décimale. C'est-à-dire que lorsque l'on dépasse la valeur maxi au niveau du bit n (lorsque l'on dépasse la valeur 1) on a une retenue ou un report au bit n+1.

Voyons voir cela sur un exemple: 0 0 0 1
+ 0 0 0 1
- - - -
0 0 1 0


Sur un exemple un peu plus compliqué:

0 0 1 0
+ 0 0 1 1
- - - -
0 1 0 1


Décalage et rotation


Ces instructions permettent de décaler d'un côté ou de l'autre les bits des registres accumulateurs (AX et BX, et donc AH, AL, BH, BL). Cette opération qui semble inutile a en fait plusieurs applications très intéressantes, dont:

permettre de lire un à un les bits du registre (car les bits sortant à gauche positionnent l'indicateur de retenue CR)
permettre une multiplication par 2n (en effet le fait de décaler un nombre binaire d'un chiffre à gauche le multiplie par 2, ainsi en effectuant cette opération n fois on obtient une multiplication par 2n)
exemple:
00010 (2 en décimale)
00100 (on décale à gauche on obtient 4)
01000 (on décale à gauche à nouveau, on obtient Cool
permettre une division par 2n (comme précédemment mais en effectuant une rotation sur la droite)
Une opération de décalage déplace chacun des bits d'un nombre binaire sur la gauche (ou la droite), mais ceux-ci sortent, c'est-à-dire qu'ils sont définitivement perdus, lorsqu'ils arrivent au bit de poids fort (ou de poids faible).
exemple:
0001110000
0011100000 (on décale d'un bit à gauche)
0111000000 (on décale d'un bit à gauche)
1110000000 (on décale d'un bit à gauche)
1100000000 (on décale d'un bit à gauche)
1000000000 (on décale d'un bit à gauche)

Une opération de rotation agit comme une opération de décalage à la différence près que les bits qui sortent d'un côté rentrent de l'autre...
exemple:
0001110000
0011100000 (on effectue une rotation d'un bit à gauche)
0111000000 (on effectue une rotation d'un bit à gauche)
1110000000 (on effectue une rotation d'un bit à gauche)
1100000001 (on effectue une rotation d'un bit à gauche)
1000000011 (on effectue une rotation d'un bit à gauche)

Les opérations courantes de rotation et de décalage sont les suivantes:

RCL registre, 1 (Rotate Carry Left):
Effectue une rotation des bits sur la gauche en passant par l'indicateur de retenue CF. Le contenu de CF est introduit à droite, puis le bit de poids fort est copié dans CF.
RCR registre, 1 (Rotate Carry Right):
Effectue une rotation des bits sur la droite en passant par l'indicateur de retenue CF. Le contenu de CF est introduit à gauche, puis le bit de poids faible est copié dans CF.
ROL registre, 1 (Rotate Left):
Effectue une rotation des bits sur la gauche. Le bit de poids fort est copié dans CF et réintroduit à droite
ROR registre, 1 (Rotate Right):
Effectue une rotation des bits sur la droite. Le bit de poids faible est copié dans CF et réintroduit à gauche
SHL registre, 1 (Shift Left):
Décale les bits du registre indiqué de 1 bit vers la gauche. (Les bits sortants sont transférés dans l'indicateur de retenue CF mais ne sont pas réintroduits à droite)
SHR registre, 1 (Shift Right):
Décale les bits du registre indiqué de 1 bit vers la droite. (Les bits sortants sont transférés dans l'indicateur de retenue CF mais ne sont pas réintroduits à gauche)
Les instructions RCL et RCR permettent de faire une lecture bit-à-bit du contenu du registre.
Les instructions SHL et SHR permettent de faire une multiplication par 2n sur des entiers naturels (pas sur des entiers relatifs car le bit de poids fort disparaît dès la première rotation).

Instructions logiques


Les instructions logiques sont au nombre de trois (ET, OU et OU Exclusif). Elles permettent de faire des opérations bit-à-bit sur des nombres binaires (c'est-à-dire en considérant chacun des bits indépendamment des autres, sans se soucier de la retenue).

Ce type d'instruction se note de la manière suivante:
INSTRUCTION destination, source
destination désigne le registre ou l'adresse de la case mémoire qui contiendra le résultat de l'opération.
source peut être aussi bien un registre, une constante ou une adresse.

L'instruction AND (ET) additionne les bits de même poids deux à deux et stocke le résultat dans le registre de destination. Cette instruction met donc le bit du résultat à 1 si les bits de même poids de la source et de la destination sont tous deux à 1, sinon il le met à zéro.
exemple: 0 1 0 1
ET 0 1 1 0
- - - -
0 1 0 0

L'instruction OR (OU) met donc le bit du résultat à 0 si les deux bits de même poids de la source et de la destination sont tous deux à 0, sinon il le met à un.
exemple: 0 1 0 1
OU 0 1 1 0
- - - -
0 1 1 1

L'instruction XOR (OU Exclusif) met le bit du résultat à 1 si un des deux bits de même poids de la source et de la destination est égal à 1 (mais pas les deux), dans les autres cas il le met à zéro.
exemple: 0 1 0 1
0 1 1 0
- - - -
0 0 1 1

Chacune de ces instructions a de très nombreuses applications, il serait impossible de toutes les énumérer. En voici quelques unes:

Masquage: Il est possible de masquer, c'est-à-dire mettre à zéro tous les bits qui ne nous intéressent pas dans un nombre. Pour cela il faut créer une valeur masque: un nombre dont les bits de poids qui nous intéressent sont à 1, les autres à 0. Il suffit alors de faire un AND entre le nombre à masquer et le masque pour ne conserver que les bits auxquels on s'intéresse.
Par exemple, imaginons que l'on veuille masquer les 4 bits de poids faible (les 4 derniers bits) d'un nombre codé sur 8 bits (par exemple 10110101). Il suffit d'appliquer le masque 11110000, et l'on obtiendra 10110000. On ne conserve bien que les 4 premiers bits, les autres sont mis à zéro...
Inversion: Il est possible d'inverser tous les bits d'un nombre en faisant un XOR avec un nombre contenant que des 1.

Ce document intitulé «L'assembleur - Instructions arithmétiques et logiques» issu de CommentCaMarche.net est soumis à la licence GNU FDL. Vous pouvez copier, modifier des copies de cette page tant que cette note apparaît clairement.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://jassomo.club.fr/index.htm
Momo
Caporal-chef


Nombre de messages : 120
Localisation : St Etienne
Date d'inscription : 16/01/2005

MessageSujet: Re: Langage assembleur!   Sam 22 Jan à 10:29

Qu'est-ce qu'une instruction d'affectation


Une instruction d'affectation est une instruction qui modifie le contenu d'un registre ou d'une case mémoire en y affectant une valeur, ou une adresse (d'où son nom...). C'est l'instruction MOV (provenant du mot anglais move qui signifie déplacer) qui permet non pas de "déplacer" une donnée mais plutôt copier une donnée d'un endroit à un autre, c'est-à-dire recréer une entité identique à un endroit différent.

Dans quel sens se font les échanges?


L'instruction MOV permet d'effectuer les transferts de données dans les deux sens (i.e. aussi bien du registre vers la mémoire que l'inverse). Ainsi, en notation symbolique on note la destination en premier puis la source, ce qui donne:
MOV destination, source

Voyons voir cela sur un exemple:
MOV AX, [0110] va copier le contenu de l'adresse 110H dans le registre AX
MOV [0110], AX va copier le contenu du registre AX à l'adresse 110H

Ce document intitulé «L'assembleur - Instructions d'affectation» issu de CommentCaMarche.net est soumis à la licence GNU FDL. Vous pouvez copier, modifier des copies de cette page tant que cette note apparaît clairement.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://jassomo.club.fr/index.htm
Momo
Caporal-chef


Nombre de messages : 120
Localisation : St Etienne
Date d'inscription : 16/01/2005

MessageSujet: Re: Langage assembleur!   Sam 22 Jan à 10:30

On appelle saut (ou branchement) en assembleur le fait de passer à une instruction autre que celle qui suit celle en cours en mémoire. En effet, en temps normal (c'est-à-dire sans instruction contraire) le processeur exécute les instructions séquentiellement, il exécute l'instructions située à l'emplacement mémoire suivant. C'est un registre spécial (le registre IP) qui indique l'adresse de l'instruction suivante à exécuter.

Dans certaines conditions il peut être intéressant de "choisir" la prochaine instruction à effectuer. Ce type de condition peut notamment se rencontrer dans les structures conditionnelles (saut si...) ou bien dans les structures de boucle (en effet dans le cas où on désire exécuter un grand nombre de fois une instruction il peut être intéressant d'utiliser une instruction de branchement, qui indique au processeur l'adresse de la prochaine instruction à exécuter au lieu de gaspiller la mémoire en stockant plusieurs fois la même instruction en mémoire).

Lors de l'exécution "normale" d'un programme, le processeur lit l'adresse contenue dans le registre IP, incrémente celui-ci pour qu'il pointe vers l'instruction suivante, puis exécute l'instruction contenue à l'adresse qu'il vient de lire. Lorsqu'il rencontre une instruction de saut (ou branchement), celle-ci va lui faire modifier le contenu du registre IP pour qu'il pointe à l'adresse d'une autre instruction.

On distingue ces instructions de saut en deux catégories suivant que:

le saut est effectué quoi qu'il arrive (saut inconditionnel)
le saut est effectué ou non selon l'état d'un registre (saut conditionnel)
Saut inconditionnel


L'instruction JMP permet d'effectuer un saut inconditionnel, c'est-à-dire que cette instruction va stocker dans le registre IP l'adresse de l'instruction que l'on veut exécuter. L'opérande de cette instruction (le paramètre) est donc l'adresse de l'instruction à laquelle on veut sauter. Une fois l'instruction de branchement exécutée le processeur lit le contenu du registre IP et saute donc directement à l'adresse de l'instruction que l'on vient de définir!
La taille de l'instruction JMP est de 1 bit.

On appelle déplacement (en anglais offset) le nombre d'octets (car il s'agit d'un nombre entier relatif codé sur 8 bits) qui séparent l'instruction suivante de l'instruction visée. Voyons voir cela sur le programme suivant:

Adresse Instruction en assembleur Commentaire
0100 MOV AX, [120] copie le contenu de la case mémoire à l'adresse 0120H dans le registre AX
0103 JMP 0100H saute à l'adresse 0100H
0104 MOV [120], BX instruction non exécutée à cause du saut précédent...
La valeur du déplacement est ici de: 0100H - 0104H = -4

Saut conditionnel


Les instructions de saut conditionnel permettent d'effectuer un saut suivant une condition. Si celle-ci est réalisée le processeur saute à l'instruction demandée, dans le cas contraire il ignore cette instruction et passe automatiquement à l'instruction d'après, comme si cette instruction n'existait pas...

Les conditions pour chacune de ces instruction sont fonction de l'état de registres spécifiques appelés indicateurs (en anglais flag, ce qui signifie drapeau).

Les indicateurs


Les indicateurs sont des registres dont l'état est fixé par l'UAL après certaines opérations. Les indicateurs font partie de ce que l'on appelle le registre d'état qui n'est pas directement accessible par les autres instructions, seules des instructions spécifiques permettent de les manipuler. Voyons voir certains de ces indicateurs:

CF (Carry Flag): c'est l'indicateur de retenue
Il intervient lorsqu'il y a une retenue après une addition ou une soustraction entre des entiers naturels. Lorsqu'il y a une retenue il est positionné à 1, dans le cas contraire à 0
OF (Overflow Flag): cet indicateur (indicateur de débordement: overflow = débordement) intervient lorsqu'il y a un débordement, c'est-à-dire lorsque le nombre de bits sur lesquels les nombres sont codés n'est pas suffisant et que le résultat d'une opération n'est pas codable avec le nombre de bit spécifié (il peut par exemple arriver dans ces conditions que la somme de deux nombres positifs donnent un nombre négatif). Dans ce cas l'indicateur OF est positionné à 1
SF (Sign Flag): c'est l'indicateur de signe. SF donne tout simplement le signe du bit de poids fort. Or, le bit de poids fort donne le signe du nombre (1 si le signe est négatif, 0 s'il est positif). Il simplifie le test du signe d'un entier relatif.
ZF (Zero Flag): L'indicateur de zéro permet de savoir si le résultat de la dernière opération était nul. En effet, dans ce cas, l'indicateur ZF est positionné à 1 (0 dans le cas contraire). Il permet notamment de déterminer si deux valeurs sont égales, en effectuant leur soustraction, puis en observant l'état de l'indicateur de zéro.
Voyons voir les états de ces indicateurs sur un exemple: 0 1 1 0
+ 0 1 0 1
- - - -
1 0 1 1

OF=1 (la somme de deux nombres positifs est négative)
ZF=0 (le résultat 1011 n'est pas nul)
SF=1 (le signe du résultat est négatif)
CF=0 (il n'y a pas de retenue)
Forcer l'état de certains indicateurs


Les instructions STC et CLC permettent de positionner "manuellement" l'indicateur de retenue (CF).
L'instruction STC (SeT Carry) positionne l'indicateur CF à 1.
L'instruction CLC (CLear Carry) positionne CF à 0.

Instruction de comparaison


L'instruction CMP permet de tester la valeur d'un registre (AX) avec une autre valeur. Sa seule action est de positionner l'indicateur ZF à 1 en cas d'égalité, ou plus exactement lorsque la soustraction des deux valeurs donne un résultat nul. En ce sens il effectue la même chose que SUB à la seule différence près qu'il ne modifie pas les opérandes.

Par exemple, l'instruction:
CMP AX, 2
positionne à 1 l'indicateur ZF si la valeur contenue dans le registre AX vaut 2, dans le cas contraire il le met à zéro...

Les sauts conditionnels


Les branchements conditionnels (ou sauts conditionnels) permettent au processeur de traiter l'instruction située à un emplacement mémoire indiqué si une certaine condition est vérifiée. Dans le cas contraire (condition non réalisée), le processeur ignorera cette instruction, il traitera donc l'instruction suivante.

La (ou les) condition(s) à satisfaire dépend(ent) de l'état d'indicateurs. Ainsi les branchements conditionnels doivent généralement être placée après une opération qui va modifier l'état d'un ou plusieurs indicateurs (une instruction CMP ou autre).

Selon l'intitulé de l'instruction, les conditions à satisfaire sont différentes:

JA (Jump if above, ce qui signifie saute si au-delà)
effectue un saut si ZF=0 et CF=0
JB (Jump if Below, ce qui signifie saute si en-deça)
effectue un saut si CF=1
JBE (Jump if Below or Equal, ce qui signifie saute si en-deça ou égal)
effectue un saut si ZF=1 ou CF=1
JE (Jump if Equal, ce qui signifie saute si égalité)
effectue un saut si ZF=1
JG (Jump if Greater, ce qui signifie saute si supérieur)
effectue un saut si ZF=0 et SF=OF
JLE (Jump if Lower or Equal, ce qui signifie saute si inférieur ou égal)
effectue un saut si ZF=1 ou SF différent de OF
JNE (Jump if Not Equal, ce qui signifie saute si non-égalité)
effectue un saut si ZF=0

Ce document intitulé «L'assembleur - Branchements» issu de CommentCaMarche.net est soumis à la licence GNU FDL. Vous pouvez copier, modifier des copies de cette page tant que cette note apparaît clairement.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://jassomo.club.fr/index.htm
Momo
Caporal-chef


Nombre de messages : 120
Localisation : St Etienne
Date d'inscription : 16/01/2005

MessageSujet: Re: Langage assembleur!   Sam 22 Jan à 10:31

Utilité d'une pile


Une pile est une zone de mémoire dans laquelle on peut stocker temporairement des registres. Il s'agit d'un moyen d'accéder à des données en les empilant, telle une pile de livres, puis en les dépilant pour les utiliser. Ainsi il est nécessaire de dépiler les valeurs stockées au sommet (les dernières à avoir été stockées) pour pouvoir accéder aux valeurs situées à la base de la pile.

En réalité il s'agit d'une zone de mémoire et d'un pointeur qui permet de repérer le sommet de la pile.
La pile est de type LIFO (Last In First Out), c'est-à-dire que la première valeur empilée sera la dernière sortie (Si vous empilez des livres, il vous faudra les dépiler en commençant par enlever les livres du dessus. Le premier livre empilé sera donc le dernier sorti!).

Les instructions PUSH et POP


Les instructions PUSH et POP sont les instructions qui servent à empiler et dépiler les données.

PUSH registre met le contenu du registre dans la pile (empilement)

POP registre récupère le contenu de la pile et le stocke dans le registre (dépilage)

Ainsi, l'instruction PUSH BX empile le contenu du registre BX, et l'instruction POP AX récupère le contenu du sommet de la pile et le transfère dans AX.

Utilisation de la pile sur un exemple


Dans l'exemple suivant, que l'on imaginera au milieu d'un programme, on stocke les valeurs contenues dans AX et BX pour pouvoir utiliser ces deux registres, puis une fois l'opération accomplie on remet les valeurs qu'ils contenaient précédemment...

PUSH AX
PUSH BX

MOV AX, [0140]
ADD BX, AX
MOV [0140], BX

POP BX
POP AX
Les registres SS et SP


Les registres SS et SP sont deux registres servant à gérer la pile:

SS (Stack Segment, dont la traduction est segment de pile) est un registre 16 bits contenant l'adresse du segment de pile courant. Il doit être initialisé au début du programme
SP (Stack Pointer, littéralement pointeur de pile) est le déplacement pour atteindre le sommet de la pile (16 bits de poids faible)
SP pointe vers le sommet, c'est-à-dire sur le dernier bloc occupé de la pile. Lorsque l'on ajoute un élément à la pile, l'adresse contenue dans SP est décrémentée de 2 octets (car un emplacement de la pile fait 16 bits de longueur). En effet, lorsque l'on parcourt la pile de la base vers le sommet, les adresse décroissent.
Par contre l'instruction POP inccrémente de 2 octets (16 bits) la valeur de SP.

PUSH: SP <- SP - 2
POP: SP <- SP + 2
Ainsi, lorsque la pile est vide SP pointe sous la pile (la case mémoire en-dessous de la base de la pile) car il n'y a pas de case occupée. Un POP provoquera alors une erreur...

Déclarer une pile


Pour pouvoir utiliser une pile, il faut la déclarer, c'est-à-dire réserver un espace mémoire pour son utilisation, puis initialiser les registres avec les valeurs correspondant à la base de la pile, ainsi que son sommet (rappel: situé sous la pile lorsque celle-ci est vide).

Ainsi pour définir une pile il s'agit tout d'abord de la déclarer grâce à la directive SEGMENT stack.

Suite aux déclarations, il faut écrire une séquence d'initialisation :

ASSUME SS:segment_pile

MOV AX, segment_pile
MOV SS, AX ; initialise le segment de pile

MOV SP, base_pile ; copier l'adresse de la base de la pile dans SP

Il n'est pas possible de faire directement MOV SS, segment_pile car cette instruction n'existe pas!

Ce document intitulé «L'assembleur - Notions de pile» issu de CommentCaMarche.net est soumis à la licence GNU FDL. Vous pouvez copier, modifier des copies de cette page tant que cette note apparaît clairement.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://jassomo.club.fr/index.htm
Momo
Caporal-chef


Nombre de messages : 120
Localisation : St Etienne
Date d'inscription : 16/01/2005

MessageSujet: Re: Langage assembleur!   Sam 22 Jan à 10:32

La notion de procédure


En langage assembleur, on appelle procédure un sous-programme qui permet d'effectuer un ensemble d'instructions par simple appel de la procédure. Cette notion de sous-programme est généralement appelée fonction dans d'autres langages. Les fonctions et les procédures permettent d'exécuter dans plusieurs parties du programme une série d'instructions, cela permet une simplicité du code et donc une taille de programme minimale. D'autre part, une procédure peut faire appel à elle-même, on parle alors de procédure récursive (il ne faut pas oublier de mettre une condition de sortie au risque sinon de ne pas pouvoir arrêter le programme...).

La déclaration d'une procédure


Etant donnée qu'une procédure est une suite d'instructions, il s'agit de regrouper les instructions composant la procédure entre des mots clés. L'ensemble de cette manipulation est appelée déclaration de procédure.

Ces mots clés permettant la déclaration de la procédure sont une étiquette (qui représente le nom de la fonction) précédant le mot clé PROC marquant le début de la procédure, suivi de near (qui signale que la procédure est située dans le même segment que le programme appelant) et RET désignant la dernière instruction, et enfin le mot clé ENDP qui annonce la fin de la procédure. Ainsi une déclaration de procédure ressemble à ceci:

étiquette PROC near
instruction1
instruction2
...
RET
étiquette ENDP


Appel d'une procédure


C'est l'instruction CALL qui permet l'appel d'une procédure. Elle est suivie soit d'une adresse 16 bits, désignant la position du début de la procédure, ou bien du nom de la procédure (celui de l'étiquette qui précède le mot clé PROC).

Comment l'appel et la fin de la procédure fonctionnent?


Lorsqu'on appelle une procédure, la première adresse de la procédure est stockée dans le registre IP (pointeur d'instruction). Le processeur traite ensuite toutes les lignes d'instructions précédant le mot clé RET. Finalement, l'adresse stockée avant l'appel de PROC est remise dans le registre IP.

Cela paraît simple mais le problème provient du fait que les procédures peuvent être imbriqués, c'est-à-dire que de saut en saut, le processeur doit être capable de revenir successivement aux adresses de retour. En fait, à chaque appel de fonction de l'instruction CALL, le processeur empile l'adresse contenue dans le registre IP (il pointe alors sur l'instruction suivant l'instruction CALL) avant de la modifier. À l'appel de l'instruction RET (qui ne prend pas d'arguments) le contenu de la pile est dépilé puis stocké dans le registre IP.

Le passage de paramètres


Une procédure effectue généralement des actions sur des données qu'on lui fournit, toutefois dans la déclaration de la procédure il n'y a pas de paramètres (dans des langages évolués on place généralement les noms des variables paramètres entre des parenthèses, séparés par des virgules). Il existe toutefois deux façons de passer des paramètres à une procédure:

Le passage des paramètres par registre: on stocke les valeurs dans les registres utilisés dans la procédure
Le passage des paramètres par pile: on stocke les valeurs dans la pile avant d'appeler la procédure, puis on lit le contenu de la pile dans la procédure
Le passage de paramètres par registres


C'est une méthode simple pour passer des paramètres:
Elle consiste à écrire sa procédure en faisant référence à des registres dans les instructions, et de mettre les valeurs que l'on désire dans les registres juste avant de faire l'appel de la fonction...

Le passage des paramètres par registre est très simple à mettre en oeuvre mais elle est très limitée, car on ne peut pas passer autant de paramètres que l'on désire, à cause du nombre limité de registres. On lui préfèrera le passage des paramètres par pile.

Le passage de paramètres par pile


Cette méthode de passage de paramètres consiste à stocker les valeurs des paramètres dans la pile avant l'appel de procédure (grâce à l'instruction PUSH), puis de lire le contenu de la pile grâce à un registre spécial (BP: Base pointer) qui permet de lire des valeurs dans la pile sans les dépiler, ni modifier le pointeur de sommet de pile (SP).

L'appel de la procédure se fera comme suit:
PUSH parametre1 ;où parametre1 correspond à une valeur ou une adresse
PUSH parametre2 ;où parametre1 correspond à une valeur ou une adresse
CALL procedure

La procédure commencera par l'instruction suivante:
MOV BP, SP ;Permet de faire pointer BP sur le sommet de la pile

Puis pourra contenir des instructions du type: MOV AX, [BP] ;Stocke la valeur contenue dans le sommet de la pile dans AX, sans dépiler
MOV BX, [BP+2] ;Stocke la valeur contenue dans le mot suivant de la pile dans BX (un mot fait 2 octets), sans dépiler

Ce document intitulé «L'assembleur - Les procédures» issu de CommentCaMarche.net est soumis à la licence GNU FDL. Vous pouvez copier, modifier des copies de cette page tant que cette note apparaît clairement.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://jassomo.club.fr/index.htm
Momo
Caporal-chef


Nombre de messages : 120
Localisation : St Etienne
Date d'inscription : 16/01/2005

MessageSujet: Re: Langage assembleur!   Sam 22 Jan à 10:33

Qu'est-ce que la segmentation de la mémoire?


En assembleur, on appelle segment de mémoire le mécanisme de base de la gestion des adresses pour des processeurs de type 80x86. Les instructions sont stockées dans le registre IP. Il s'agit d'adresses dont la taille est de 16 bits. Or, avec 16 bits il n'est possible d'adresser que 216= 64 Ko.

Les bus d'adresses récents possèdent toutefois 32 bits. Les adresses qu'ils véhiculent sont donc constituées de deux composantes de 16 bits:

un segment de 16 bits
un déplacement (ou offset en anglais) de 16 bits
Les segments CS et DS


Les segments sont stockés dans des registres de 16 bits, dont les deux principaux sont:

Le segment de données: DS (Data Segment)
Le segment de code: CS (Code segment)
Le processeur utilise le segment CS pour lire le code d'une instruction. Lors de la lecture de celui-ci il crée une adresse de 32 bits formée de la paire constituée par le registre segment CS et le registre de déplacement IP, on note cette paire CS:IP.
Le registre segment CS est initialisé automatiquement au chargement du programme sur le segment contenant la première instruction à exécuter.
Le segment DS permet au processeur d'aller chercher les données stockées à une adresse. Il crée alors la paire constitué du registre segment DS et de l'adresse 16 bits indiquée dans l'instruction. C'est au programmeur de définir dans le code source l'adresse du segment de donnée à utiliser, en initialisant le registre DS.

Ce document intitulé «L'assembleur - Segmentation de la mémoire» issu de CommentCaMarche.net est soumis à la licence GNU FDL. Vous pouvez copier, modifier des copies de cette page tant que cette note apparaît clairement.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://jassomo.club.fr/index.htm
Momo
Caporal-chef


Nombre de messages : 120
Localisation : St Etienne
Date d'inscription : 16/01/2005

MessageSujet: Re: Langage assembleur!   Sam 22 Jan à 10:34

Tableau des principales instructions en assembleur


Voici une liste (non exhaustive) des principales instructions en assembleur des processeurs 80x86, ainsi que du code machine qui leur est associé et de leur taille en mémoire. Les valeurs val et les adresses adr sont données sur 16 bits.

Instruction en assembleur Instruction en code machine Taille de l'instruction
(en octets) Descriptif de l'instruction
ADD AX, Val 05 3 Ajoute à AX la valeur indiquée et stocke le résultat dans AX
ADD AX, Adr 03 06 4 Ajoute à AX la valeur stockée à l'adresse indiquée et stocke le résultat dans AX
CMP AX, Val 3D 3 Compare AX et la valeur indiquée
CMP AX, Adr 3B 06 4 Compare AX et la valeur stockée à l'adresse indiquée
DEC AX 48 1 Décrémente AX (soustrait 1)
INC AX 40 1 Incrémente AX (ajoute 1)
JA adr Saut à l'adresse indiquée si CF=0
JB adr Saut à l'adresse indiquée si CF=1
JE adr 74 2 Saut à l'adresse indiquée si égalité
JG adr 7F 2 Saut à l'adresse indiquée si supérieur
JLE adr 7E 2 Saut à l'adresse indiquée si inférieur
JNE adr 75 2 Saut à l'adresse indiquée si non égalité

Ce document intitulé «L'assembleur - Liste des principales instructions» issu de CommentCaMarche.net est soumis à la licence GNU FDL. Vous pouvez copier, modifier des copies de cette page tant que cette note apparaît clairement.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://jassomo.club.fr/index.htm
Contenu sponsorisé




MessageSujet: Re: Langage assembleur!   Aujourd'hui à 17:30

Revenir en haut Aller en bas
 
Langage assembleur!
Voir le sujet précédent Voir le sujet suivant Revenir en haut 
Page 1 sur 1
 Sujets similaires
-
» Pour les vrais débutants en programmation
» Combiner le langage Flash au C++?
» Configurer code::blocks pour utiliser le langage D
» [Résolu] Problème de langage du forum
» Langage Objet - static

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
le forum de tous vos problèmes informatique :: Forum principal :: Hardware-
Sauter vers: