★ CODING ★ CLASSEURS WEKA ★ Comment exploiter toutes les ressources et augmenter les performances de votre AMSTRAD CPC ★ |
4/2.11 III - Les interruptions logicielles (SOFT) (16e Complément) | Coding Classeurs Weka |
4/2 - Assembleur Z80 : Définitions et rappels de base4/2.11 Les interruptions sur Amstrad III - Les interruptions logicielles (SOFT) A partir du signal INT qui branche sur un programme de traitement (voir Partie 9, Chap. 8.12, pages 6 à 8), sont gérées ce que l'on appellera des interruptions logicielles. Cela signifie que ce sont des interruptions qui sont installées par le programmeur, et qui sont placées à des endroits bien déterminés pour pouvoir les utiliser. Il existe trois interruptions logicielles que l'on appelle dans l'ordre de leurs priorités :
Dans chacune de ces interruptions il est possible à vous, utilisateur, d'insérer vos propres routines de traitement, en plus de celles déjà existantes ; certaines pouvant même être programmables. Dans la suite de notre exposé, nous appellerons, un peu abusivement, mais pour utiliser le même langage que beaucoup de programmeurs sur CPC, chaque traitement que nous pourrons ajouter, une interruption. Avant d'entrer dans l'étude de la gestion de ces trois types d'interruptions, nous allons définir ici les termes que vous rencontrerez souvent dans nos explications et dans tout ce qui concernera les interruptions en langage machine :
Heureusement pour le programmeur, la gestion de ce pointeur est totalement transparente, car effectuée par le logiciel de base. Nous allons pouvoir maintenant étudier une à une les différentes interruptions programmables en langage machine, et nous verrons comment insérer soi-même sa propre routine d'interruption dans chacune d'elle. L'interruption fast ticker FAST TICKER est l'interruption la plus rapide conçue sur l'AMSTRAD-CPC. Elle est générée grâce au VGA sur la broche INT du microprocesseur Z80. Nous avons étudié, Partie 9, Chapitres 8.11 et 8.12 dans la création d'un programme de sauvegarde écran et d'un utilitaire de CAPS LOCK interactif, comment détourner le traitement de cette interruption, et par là même insérer d'autres traitements. Cette façon de procéder, même si elle est particulièrement simple et adaptée dans le programme proposé alors, est peu orthodoxe car elle rend la routine ajoutée comme étant la plus prioritaire, ce qui n'est pas toujours le cas, et dans l'éventualité de traitements longs elle perturberait le fonctionnement de votre CPC. Il a été en effet prévu des vecteurs en RAM permettant d'ajouter et d'ini-tialiser un nouvel événement, de le désactiver et le réactiver à volonté. Il est même possible d'ajouter d'autres événements ultérieurement. Ajouter et initialiser un événement Nous vous proposons d'étudier la façon dont est ajouté un nouvel événement de type FAST TICKER. Premièrement, il nous faut connaître le vecteur placé en RAM qui permet cet ajout. Vous trouverez cette adresse Partie 4, Chap. 2.7, page 55 : il s'agit de &BCE0 qui est le vecteur accédant à la routine dénommée KL-NEW-FAST-TICKER. Cette routine initialise et positionne un bloc dans la file d'attente d'interruption rapide. Avant d'étudier comment nous allons pouvoir placer un bloc à l'aide de KL-NEW-FAST-TICKER, nous vous proposons d'étudier la façon dont le logiciel de base insère le bloc. Précisons auparavant que cette étude a été effectuée sur CPC-6128, que les adresses que nous vous fournirons sont identiques sur CPC-664, mais qu'elles sont peut-être légèrement différentes sur CPC-464. Par contre la façon dont la routine insère le bloc doit être identique, ce qui ne change rien à notre étude. Pour étudier la routine, comme pour toute routine Assembleur que vous désirez extraire de la ROM pour la décortiquer, il nous faut en connaître les conditions d'entrée, sous peine de devoir les rechercher, ce qui n'est pas impossible, mais demande une grande compétence et un travail acharné sur l'Assembleur et l'organisation de la mémoire du CPC. Les conditions d'entrée portent sur 6 registres du Z80 : le registre double HL doit contenir l'adresse du bloc d'interruption, le registre B contient le type d'interruption, C contient le numéro de la ROM à sélectionner pour traiter l'interruption, et le registre double DE contient l'adresse de la routine exécutant la procédure d'interruption. Une question se pose : Que doit, ou va contenir le bloc d'interruption, et quelle taille doit-il atteindre ? (i.e. combien d'adresses mémoire doit-il occuper ?). L'étude qui suit à pour but de donner une réponse à ces questions. Le vecteur de KL-NEW-FAST-TICKER, par l'intermédiaire d'une instruction RESTART, notée RST, effectue une commutation de la ROM inférieure, la ROM du système d'exploitation, et se branche directement à l'adresse &0176. A partir de cette adresse, nous trouvons le programme suivant : 0176 E5 KLNFT: PUSH HL |
|
L'initialisation du bloc s'effectue par chargement de HL avec l'adresse du bloc d'événement (BLOCEV) de 9 octets réservé (DEFS 9).
Le registre DE est chargé avec l'adresse de la routine (DEPART).
Le registre B est chargé avec la valeur &81 qui correspond à la valeur binaire &B10000001, ce qui signifie que l'événement est asynchrone (b7 = 1 ), donc il en est tenu compte même en mode programmation, il n'est pas express (b6 = 0), et ne possède aucune priorité par rapport à d'autres événements (b4b3b2b1 = 0000) (à quoi bon ?). On signale par bO = 1 que la routine de traitement est en RAM centrale.
Le registre C n'est pas affecté puisque la routine est en RAM.
Dans la routine de traitement, il nous est possible de calculer la période d'apparition des BIPs. Nous ne tiendrons pas compte des temps d'exécutions des instructions (de l'ordre de quelques microsecondes par rapport à 3,3 millisecondes qui est la période d'appel de la routine). Le compteur est initialisé à la valeur &0000 (COMPT: DEFB 00,00), et ne repassera à zéro qu'après un tour complet, c'est-à-dire 65536 appels plus tard. Le temps est donc de 1/300 x 65536 = 3,3 x 10-3 x 65536 = 219 secondes, ce qui nous donne un temps approximatif de 3 mn 39 s.
Pour ceux qui désirent expérimenter cette routine et qui ne possèdent pas de logiciel d'assemblage, nous fournissons ci-dessous le chargeur Basic correspondant.
|
Les explications pour son utilisation sont insérées dans le programme, on conseillera cependant de sauvegarder celui-ci et de retirer la disquette du lecteur avant de lancer son exécution.
Pour créer une horloge s'affichant régulièrement, nous avons tout de suite pensé à la placer sous interruption à l'aide de KL-NEW-FAST-TICKER. il nous fallait aussi trouver une façon simple de la mettre à l'heure, nous avons donc créé une instruction résidente au Basic (RSX) que l'on a appelé ÙHEURE (ou ! HEURE selon le type de CPC que vous possédez) à laquelle nous fournirons la valeur des heures et des minutes par la syntaxe suivante : ùHEURE,hh,mm.
Nous n'avons pas tenu compte des secondes dans la mise à l'heure, ni dans l'affichage, car cela prendrait un temps non négligeable dans l'exécution (la fonction d'affichage est celle qui occupe le plus de temps). Cet affichage se présentera sous la forme suivante, par exemple pour 13 heures 56 minutes : 13:56 ou encore 13 56.
L'affichage du caractère deux points sera intermittent, toutes les secondes nous afficherons soit l'une des possibilités, soit l'autre, et ce au même endroit, ce qui fera croire à un clignotement du caractère.
Nous avons choisi cette possibilité d'affichage, premièrement pour signaler, lors d'un arrêt de la frappe au clavier, que l'horloge est toujours en fonctionnement, deuxièmement, pour réafficher l'horloge lors d'un scrol-ling vertical montant.
Lors de l'exécution de certains logiciels, il est possible que l'affichage de l'heure perturbe l'écran, aussi, avons-nous prévu l'inhibition de celui-ci, mais sans arrêt du comptage, ainsi vous pourrez restaurer l'affichage, sans perdre l'heure
ùHON restaure l'affichage de l'heure,
ùHOFF inhibe l'affichage de l'heure.
Un dernier point à notre cahier des charges était de respecter l'emplacement de l'heure quel que soit le mode d'affichage (MODE 0, 1 ou 2). Ceci fut effectué par l'utilisation d'un vecteur fournissant les dimensions de l'écran en caractères, il s'agit de SCR-CHAR-LIMITS qui, sans condition d'entrée, fournit dans B le numéro de la dernière colonne de l'écran, et dans C le numéro de la dernière ligne. Connaissant le nombre de colonnes, il nous est possible de déterminer l'emplacement de la dizaine des heures (4 caractères devant, l'unité des minutes se trouvant sur la dernière colonne). Ainsi, quel que soit le mode d'affichage, l'affichage de l'heure occupera toujours les 5 caractères en haut à droite de l'écran (il n'y a aucun problème pour le nombre de lignes, car celui-ci est identique dans les deux modes).
L'ordinogramme de traitement de l'interruption se présente ainsi :
|
Ce qui donne le programme Assembleur suivant :
|
Adresses &A000 à &A00B : les instructions créées en RSX, pointées par la table « VECTEU », sont insérées au Basic avec le vecteur KLOGTXT (KL-LOG-TEXT) qui demande un bloc réservé aux adresses &A01A à &A01D.
Adresses &A00E à &A019 : le bloc d'événement est installé et initialisé par KLNEWT (KL-NEW-FAST-TICKER), le bloc est réservé aux adresses &A036 à &A03E.
La routine mettant à jour le compteur horaire débute en &A03F. A partir de cette adresse, il est effectué un décompte du contenu de l'adresse (COMPT), qui est initialisée à chaque annulation avec la valeur &012C. Ce qui nous donne un temps à peu près égal à 1 seconde compte tenu des temps pris pour l'exécution de la routine.
Ainsi toutes les secondes, la variable SECOND est remise à jour, MINUTE et HEURE le sont aussi, si cela est utile.
A chaque seconde écoulée, le contenu de (DPOINT) est testé pour afficher soit un espace, soit le caractère deux points (Adresses &A050 à &A05D).
Le programme d'affichage débute en &A099. A l'initialisation, il est placé le code RET (&C9), qui permet le retour au Basic sans effectuer d'affichage. Lors de l'autorisation de l'affichage (par ùHON, voir aux adresses &A118 à &A11D), ce code est remplacé par 00 (NOP) qui n'effectue aucune opération, ce qui permet au programme de continuer à l'adresse suivante. Si on demande l'inhibition de l'affichage (ùHOFF aux adresses &A11E à &A123), le code RET est de nouveau installé en &A099.
L'affichage est effectué chiffre par chiffre, en intercalant en plus le séparateur contenu dans DPOINT. Les chiffres des dizaines sont « récupérés » par une rotation du nombre quatre fois et un masquage par la valeur &0F. En outre, le chiffre obtenu doit être transformé en caractère ASCII pour pouvoir être fourni à TXTWRC, ce qui est effectué en lui ajoutant la valeur &30.
Après affichage de tous les chiffres, le programme redonne la main au Basic.
Adresses &A0EF à &A117 : à ces adresses se trouve la routine permettant de mettre à jour l'horloge à l'aide de la commande ùHEURE,hh,mm. Cette remise à jour effectue automatiquement une initialisation des secondes à la valeur 0. Le procédé de mise à jour est à la fois simple et un peu « tordu ». Les valeurs fournies, en décimal, sont récupérées dans la pile des paramètres pointée par le registre IX. A partir de ces valeurs qui sont en hexadécimal (le microprocesseur travaillant dans cette base, il est effectué une incrémentation de 1 avec un ajustement décimal pour obtenir un nombre BCD (Binaire Codé Décimal) qui sera rangé à l'adresse appropriée.
Afin de ne pas défavoriser le programmeur Basic ne possédant pas de logiciel d'assemblage, nous fournissons ci-dessous le chargeur Basic.
|
Les directives de sauvegarde sont une fois encore incluses dans le programme, ainsi qu'une décomposition en quatre blocs des codes machine Z80, pour permettre une gestion des erreurs plus facile.
Nous vous proposons aussi ce petit programme permettant de comparer cette horloge nouvellement créée, par rapport à une horloge utilisant les interruptions logicielles du Basic.
Après avoir initialisé et visualisé l'horloge précédente, vous lancerez le programme suivant :
L'INTERRUPTION FRAME FLY
Comme son nom l'indique, cette interruption va concerner le balayage écran (FRAME).
Elle est générée à chaque retour du faisceau cathodique de balayage de l'écran de votre CPC, c'est-à-dire tous les 50* de secondes.
Comme pour FAST TICKER, il existe trois vecteurs en RAM pour initiali-ser et positionner un bloc FRAME FLY dans la file d'attente (KL-NEW-FRAME-FLY), retirer un bloc de cette file (KL-DEL-FRAME-FLY), ou le rajouter (KL-ADD-FRAME-FLY), dont vous trouverez les caractéristiques Partie 4, Chap. 2.7, page 55.
KL-NEW-FRAME-FLY
Pour ce vecteur placé à l'adresse RAM &BCD7, les conditions d'entrée sont identiques à celles de KL-NEW-FAST-TICKER.
Le programme appelé en ROM inférieure se situe à partir de l'adresse &0163 et le voici désassemblé :
On remarquera que ce programme est identique à celui de KL-NEW-FAST-TICKER, aux adresses et à la variable LISTFF près, aussi nous ne sommes pas obligés de l'étudier à nouveau.
L'interruption nécessitera donc un bloc défini de façon identique au précédent, de 9 octets, et initialisé par les registres en entrées comportant le même type de paramètres.
Son chaînage par contre sera effectué à partir de l'adresse de base &B8B9 (au lieu de &B8BB), puis se propagera dans les blocs installés.
Retirer un bloc
Encore une fois nous avons un procédé identique à celui de KL-DEL-FAST-TICKER, mais cette fois-ci pour KL-DEL-FRAME-FLY situé à l'adresse &BCDD, seule l'adresse du bloc de base est différente.
Nous vous donnons pour indication des adresses le programme appelé :
Ajouter un bloc
De procédé identique à KL-ADD-FAST-TICKER, KL-ADD-FRAME-FLY situé en &BCDA renvoi à l'adresse &016A.
Exemple d'utilisation
Afin d'utiliser FRAME FLY, nous vous proposons l'étude d'un programme générant un curseur clignotant qui vous signalera que votre CPC est toujours actif, et que vous avez la main sous Basic.
Le procédé d'installation est le même que pour FAST TICKER, ainsi nous ne reviendrons pas dessus. Signalons tout de même que nous avons donné à ce programme une priorité identique en chargeant le registre B avec la valeur &81, mais qu'il n'est traité que tout les 50e de secondes, c'est-à-dire toutes les 20 millisecondes.
La procédure ALLUMER le curseur :
La procédure ETEINT le curseur :
|
Adresses &A000 à &A00A : initialisation et chaînage du bloc événement situé en &A017.
Adresses &A00B et &A013 : on initialise les variables de temps d'allumage et d'extinction du curseur : &19 fois 0.02 seconde, ce qui donne 25 x 0.02 = 0.5 seconde pour chaque temps, ce qui donne un cycle de 1 seconde. Si vous jugez ce temps trop rapide, ou trop long, il faut modifier la valeur de l'adresse &A00C. TEMP correspond à la valeur servant à l'initialisation des deux autres variables. TEMPVI est la variable contenant le compteur de temps qu'il reste au curseur à être visible, tandis que TEMPET est celui pour lequel le curseur sera éteint.
La routine de traitement de l'interruption de type KL-NEW-FRAME-FLV se trouve à partir de l'adresse &A020.
On sauvegarde d'abord les registres, puis un test sur le temps restant au curseur à être visible est effectué. Si ce temps est nul, on va éteindre le curseur en &A046.
Sinon le curseur est allumé en décrémentant le temps restant.
Page précédente : 4/2.11 II - Les interruptions matérielles (Hard) |
|
Page créée en 369 millisecondes et consultée 442 fois L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko. |