Programmation Assembleur/x86/Interactions avec les périphériques

Un livre de Wikilivres.
Programmation Assembleur/x86
Modifier ce modèle

Le processeur n'est pas le seul composant d'un ordinateur, mais est celui qui coordonne les opérations : il interagit avec la mémoire (voir le chapitre Copie entre registres et mémoire) ; et il interagit avec les composants périphériques de la machine (lecteur de disque, timer, contrôleur d'interruptions, ...) par l'intermédiaire des bus auxquels il est connecté. Il reçoit des interruptions générées par les périphériques requérant son attention pour traiter un évènement (fin d'écriture d'un buffer sur disque, timer écoulé, ...).

Transfert de données avec les périphériques[modifier | modifier le wikicode]

Chaque composant périphérique a ses propres registres de configuration et de statut. Le processeur communique avec eux en utilisant des instructions de transfert spécifiques, utilisant le bus d'adresse et le bus de données. Cela se déroule comme pour les transferts avec la mémoire, excepté qu'une broche du bus de contrôle permet de distinguer les deux types d'accès.

Instruction Opérandes Transfert
IN r, p r, p Lecture : transfert d'un octet ou d'un mot de 16 bits du port p vers le registre r.
OUT p, r p, r Écriture : transfert d'un octet ou d'un mot de 16 bits du registre r vers le port p.

Sur 8086, le registre r est l'accumulateur donc AL ou AX, et le port peut être une constante ou le registre DX.

Exemple :

in al, 0x60

mov dx, 0x3DF
out dx, ax

Ligne "test"[modifier | modifier le wikicode]

La broche "TEST" du processeur est active à l'état bas. L'instruction WAIT provoque la suspension de l'exécution des instructions par le processeur si cette broche est à 0, jusqu'à ce qu'elle repasse à 1. Cela permet de synchroniser l'exécution avec un évènement externe. Dans les architectures PC avec coprocesseur (x87) cette instruction permet d'attendre le résultat d'opérations de calculs.

Coprocesseur x87[modifier | modifier le wikicode]

Les premiers modèles de la famille de processeurs x86 étaient dépourvus d'instructions pour le calcul avec des nombres en virgule flottante. Les langages de programmation devaient donc fournir une bibliothèque de fonctions implémentant les calculs en logiciel. Ces calculs pouvaient aussi être pris en charge matériellement par un coprocesseur (famille x87 : 8087 pour le 8086, 80287 pour le 80286).

Instructions vers le coprocesseur[modifier | modifier le wikicode]

Comme son nom l'indique, le coprocesseur fonctionne avec le processeur. Il regarde les bus d'adresse, de données et de contrôle et voit la lecture des données et des instructions. Il est connecté aussi à certaines broches du processeur (via le bus de contrôle) lui permettant de distinguer la lecture d'instructions (opcodes) de celles des autres octets d'instruction et celles des données.

L'instruction ESC (ESCape to coprocessor) est suivie d'un code d'opération de deux opérandes. Le 80x86 décode ces instructions, et si les opérandes sont des pointeurs en mémoire, envoie l'adresse sur le bus d'adresse. Le bloc mémoire adressé va alors envoyer les données lues sur le bus de données. Le 80x86 ne fait aucune autre action. Du point de vue du 80x86 cette instruction semble n'avoir aucun effet, ce qui est réellement le cas si aucun coprocesseur n'est installé. En revanche le coprocesseur 80x87 voit le code d'opération et les deux opérandes, et a à sa disposition les données lues de la mémoire si besoin.

Le coprocesseur fonctionne de manière asynchrone : si le 80x86 envoie une autre instruction alors qu'un traitement est déjà en cours, elle sera ignorée. La solution à ce problème est d'utiliser l'instruction WAIT qui suspend l'exécution des instructions par le 80x86 tant que l'état 0 est présent sur la broche TEST, celle-ci étant connectée à la broche BUSY du 80x87 que celui-ci utilise pour indiquer qu'une opération est en cours. Une autre solution consiste à exécuter d'autres instructions pour laisser du temps au coprocesseur (programmation parallèle).