| Présentation | Hardware | Programmation | Links | Divers | Contact |

L'ASSEMBLEUR

Pour bien comprendre l'assembleur, il faut déjà comprendre le fonctionnement interne d'un ordinateur. En effet, l'assembleur permet de toucher directement le système à tous les niveaux : processeur, mémoires, périphéries, etc. Donc, pour bien gérer tout ceci, nous allons donc rappeler les grandes lignes du fonctionnement d'un système informatique.

L'ordinateur

Un ordinateur se compose principalement d'un processeur (CPU), de mémoire (RAM et ROM), et de composants périphériques (clavier, port série, contrôleur en tout genre, carte son, etc.). Le CPU est bien sur le maître à bord dans un ordinateur (comme dans une console de jeux d'ailleurs), la mémoire et les périphériques étant à son service. Le CPU est connecté aux périphériques et à la mémoire à l'aide d'un bus. Le bus est une 'chaîne' ou tous les périphériques sont connectés en parallèle. Un bus système se divise généralement en trois 'sous bus' :

- Le bus de données (c'est la partie qui transporte les données brutes). Notons que plus ce bus est large plus le système sera rapide. En effet un système 16 Bits est plus rapide qu'un système 8 bits car il est capable de 'transporter' 2 octets à la fois alors que le système 8 bits n'en transporte qu'un à la fois. (1 octet=8bits)

- Le bus d'adressage (c'est celui qui désigne un endroit dans la mémoire ou un périphérique). Plus il est large plus on peut adresser de la mémoire. Exemple : bus d'adressage 16bits =64Ko addressable ,bus 32bits=4Go!)

- Le bus de contrôle (Il désigne le mode de l'opération à effectuer : Lecture ou écriture, périphérique ou Mémoire, Interruption, etc.)

Voici un exemple de diagramme d'un système :

sys.gif

Pour exécuter un programme, le CPU va chercher les instructions dans la mémoire et les exécuter de façon séquentielle. Le CPU génère pour cela les signaux nécessaires sur le bus pour lire dans la mémoire. Chaque périphérique répond à une adresse précise (par exemple sur PC, le clavier se situe a l'adresse n°96), et il ne doit pas y avoir 2 périphériques partageants la même adresse sinon il y a conflit... (courant sur PC).
Notons qu'il y a des composants permettant d'accélérer le système : par exemple, le DMA (Direct Memory Access) permet de faire des transferts entre un périphérique et la mémoire sans passer par le CPU. Les transferts sont alors très rapides et cela libère le CPU pour une autre tache.
Pour programmer sur un système, il faut alors programmer le composant principal en premier lieu : le CPU. Pour cela, on fait appel à l'Assembleur.

L'assembleur

L'Assembleur permet de contrôler directement le CPU : Ceci permet d'avoir une totale maîtrise du système et surtout permet de faire des programmes très très rapide par rapport aux langages de haut niveau (C++, Basic, ...). En effet, bien que ces langages permettent de faire des programmes facilement et rapidement, ils n'optimisent pas le code d'exécution et donc font des programmes (beaucoup) plus lent et beaucoup plus volumineux... Notons que l'on peut insérer de l'assembleur dans certains langages (Pascal et C par exemple) pour accélérer l'exécution du programme. L'assembleur permet donc de programmer le CPU, mais avant d'entrer dans le vif du sujet présentons le CPU : Le CPU (Central Processing Unit), charge, analyse et exécute les instructions présentes en mémoire de façon séquentielle, c'est-à-dire une instruction à la suite de l'autre. Le CPU contient une unité de calcul en nombre entier (ALU), d'un bus interne, d'un bus externe se connectant au système, d'un décodeur d'instructions qui comme son nom l'indique décode l'instruction compilée pour pouvoir l'exécuter, et des cases mémoires que l'on appelle les Registres.

Voici par exemple le diagramme interne du Z80 :

Z80

Ce sont les registres qui permettent la 'communication' entre le programme et le CPU. Ils sont 'l'interface' du CPU. Pratiquement toutes les données qui passent par le CPU pour être traité par celui-ci, devront se trouver dans les registres du CPU. Ces cases mémoires sont les plus rapides de tout le système... Il y a différents types de registres dans un CPU : Les registres de traitements et les registres d'adressages, et les registres d'état.

Les Registres de traitement sont les registres destinés au traitement des valeurs contenues dans celle-ci. Par exemple, on peut effectuer une addition d'un registre de traitement avec un autre registre, ou effectuer des multiplications, ou des traitements logiques...

Les Registres d'adressage permettent de pointer un endroit de la mémoire. Ils sont utilisés pour lire ou écrire dans la mémoire...

Les registres d'état (Ou volet : FLAG en anglais), sont de petits registres (de 1 Bit) indiquant l'état du processeur et 'le résultat' de la dernière instruction exécutée. Les plus courants sont le Zéro Flag (ZF) qui indique que le résultat de la dernière opération est égale a zéro (après une soustraction par exemple), le Carry Flag (CF) qui indique qu'il y a une retenue sur la dernière opération effectuée, Overflow Flag qui indique un dépassement de capacité de registre...

Pour gérer ces registres, on fait appel aux instructions du processeur : Ces instructions permettent d'effectuer des tâches très simples sur les registres. Elles permettent de mettre des valeurs dans les registres, d'effectuer des traitements logiques (Fonctions OU, ET, ...), des traitements arithmétiques, des traitements de chaîne de caractères, etc.
Ces instructions sont formées à l'aide de code binaire. Pour nous, il est beaucoup plus facile d'utiliser des mots-clés à la place de ces codes binaires obscurs... C'est pour cela que l'on fait appel aux compilateurs qui permettent de transformer un programme assembleur fait avec des mots-clés compréhensibles pour nous (mais incompréhensibles pour la machine), en un programme exécutable, compréhensible par le processeur.
Ces mots-clés ou mnémoniques, sont souvent la compression d'un mot ou d'une expression en anglais présentant l'action de l'instruction. Par exemple sur les processeurs 8086, l'instruction MUL permet la multiplication (MULtiply), sur Z80 l'instruction LD permet de charger une valeur dans un registre ou dans la mémoire (LoaD). Les instructions sont souvent suivies d'opérandes permettant d'indiquer sur quel(s) registre(s) on veut effectuer le traitement, quelle valeur on veut utiliser, etc.

Exemple : pour additionner 2 registres (2 registres 16 bits AX et BX) sur 8086 :
ADD AX, BX
Cette instruction correspond en gros à AX=AX+BX

La même chose sur 68000 :
ADD.W D1, D0
Cette instruction correspond en gros à D0=D0+D1

Sur cet exemple, nous pouvons remarquer la différence de syntaxe entre 2 processeurs différents : Lorsqu'un constructeur conçoit un processeur, il détermine aussi son assembleur. C'est pour cela que l'assembleur n'est pas universel, car il est différent sur chaque processeur (ou plutôt concepteur). Et même si par hasard une instruction est identique entre 2 CPU différents, elle ne sera pas compatible sur chaque processeur, car le code binaire correspondant sera différent. Ceci est l'un des plus gros inconvénients de la programmation en assembleur, car il faut alors reprogrammer de A à Z le logiciel si on veut le porter sur un autre processeur.
Chaque processeur comporte un nombre plus ou moins important d'instructions. Ce nombre permet de séparer 2 grandes familles :
- Les CPU RISC comportant peu d'instructions, mais étant plus rapides (instructions de même taille).
- Les CPU CISC comportant plus d'instructions, mais généralement moins performant.

Connaissant les registres et les instructions d'un processeur, on peut alors commencer à le programmer.

Pour les détails (registres, instructions, ...) sur un processeur, cliquez sur un des liens suivants :

Famille X86 (essentiellement PC)
Processeur 68000 (Atari ST, Amiga, TI89, etc.)
Processeur Z80 (ZX81, TI82, etc.)

Nous n'allons pas détailler ici chaque processeur, car il faudrait beaucoup plus qu'un site Web...
Allez voir les liens de ce site, il existe beaucoup de site parlant de la programmation en assembleur sur différents processeurs allant du Z80 au Pentium III en passant par le 68000 et autres...


(C) HxC2001 / Jean-François DEL NERO