★ CODING ★ CLASSEURS WEKA ★ Comment exploiter toutes les ressources et augmenter les performances de votre AMSTRAD CPC ★ |
4/2.11 III - Les interruptions logicielles (SOFT) (17e 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) On procède à une sélection du flux vidéo correspondant à la fenêtre active, on charge A avec la valeur 0 (adresse &A02E) avant d'appeler le vecteur TXT-STR-SELECT (adresse &A030). Ce vecteur permet d'effectuer une commutation du flux vidéo sur la fenêtre 1. Au retour elle rend le numéro du flux vidéo qui était actif dans le registre A. On procède à une sauvegarde de ce numéro dans le registre C avant d'appeler le vecteur de validation du curseur, puis l'autorisation d'allumage (adresses &A033 à &A037). L'ancien flux est récupéré dans A, puis on l'active par un nouvel appel de TXT-STR-SELECT (&A03A à &A040). La variable d'extinction est réinitialisée à sa valeur la plus élevée pour un futur comptage, puis se termine la procédure par un saut à la FIN. Le traitement de l'extinction du curseur débute en &A046 et se déroule de la même façon que la visualisation, en utilisant la variable TEMPET et les vecteurs de dévalidation du curseur (TXT-CUR-DISABLE) et d'extinction (TXT-CUR-OFF). Avant de quitter complètement la procédure, il faut penser à restaurer les registres qui ont été emplilés (adresses &A067 à &A06A).
Nous proposons le chargeur Basic de ce programme qu'il suffira de lancer après sauvegarde, et d'initialiser par CALL &A000. Si le temps d'extinction et d'allumage ne vous convient pas, il suffit de frapper la ligne suivante pour le modifier à une autre valeur : POKE &A00C, valeur Nous vous conseillons tout de même de ne pas placer une valeur trop petite sous peine de ne plus rien comprendre aux phénomènes qui se dérouleront sur votre écran. Une valeur trop grande n'apportera pas non plus d'effet intéressant. L'interruption de type EVENT En plus des deux types d'interruptions précédentes, votre AMSTRAD-CPC vous propose un autre type d'interruption, qui est l'interruption du type EVENT. Cette interruption, contrairement à FAST TICKER et FRAME FLY, est paramétrable en fréquence d'apparition. En effet, FAST TICKER est générée toutes les 3,3 millisecondes ( 1 /300e de secondes), [et FRAME FLY toutes les 20 millisecondes ( 1 /50e de secondes),] par contre TICKER peut apparaître un nombre de fois égal à n/50 (c'est-à-dire toutes les n fois 20 millisecondes), avec n pouvant varier théoriquement entre &0001 et &FFFF, ce qui nous donne une période de traitement de TICKER comprise entre 20 millisecondes et 1 310 700 millisecondes (ce qui donne 21 mn 60 secondes et 7 dixièmes). Les vecteurs permettant d'accéder à cette interruption sont KL-INIT-EVENT, KL-ADD-TICKER et KL-DEL-TICKER. Installer un bloc par KL-INIT-EVENT Ce vecteur est situé à l'adresse &BCEF (voir Partie 4, Chapitre 2.7, page 57) et permet d'initialiser un bloc d'interruption. Contrairement à KL-NEW-FAST-TICKER et KL-NEW-FRAME-FLY, l'interruption n'est pas activée, donc n'est pas placée dans la chaîne de traitement de toutes les interruptions de ce type. Les conditions d'entrées sont identiques à celles des deux vecteurs précédemment cités, c'est-à-dire HL contenant l'adresse du bloc d'interruption, B donnant le type, C contenant le numéro de la ROM à sélectionner si le traitement de l'interruption se situe en ROM, et DE pointant l'adresse de début du traitement. Le vecteur de KL-INIT-TICKER envoie en ROM à une adresse déjà étudiée : &01D2 que nous avons appelé INIT. En sortie, les différents paramètres sont sauvegardés dans le bloc pointé, et nous avons vu que INIT a traité au total sept octets, donc le registre HL doit pointer une zone de sept octets réservés pour le bloc. Un problème subsiste si nous nous arrêtons là : l'interruption est initiali-sée, mais n'est pas active. Souvenons-nous : le bloc pour les deux types d'interruptions comporte neuf octets, les deux premiers étant réservés pour l'adresse de chaînage. Hors, l'adresse de chaînage n'est pas insérée par INIT. Nous verrons qu'après avoir installé notre bloc de sept octets, de manière identique aux interruptions précédentes, il est nécessaire de l'activer, et de lui signaler sa fréquence de traitement. Initialiser un bloc par KL-ADD-TICKER L'installation du bloc étant pratiquée, vous pourrez en ordonner l'activa-tion à n'importe quel instant de votre programme à l'aide du vecteur de KL-ADD-TICKER situé en &BCE9 (voir Partie 4, chapitre 2.7, page 56). Ce vecteur permet de placer un bloc dans la file d'attente des interruptions de type TICKER. Ses conditions d'entrée sont : HL contenant l'adresse du bloc d'interruption, mais nous verrons que ce n'est pas le même que précédemment, DE contiendra la valeur initiale du compteur, et BC contiendra Ij valeur de réarmement du compteur. Pour découvrir quel bloc pointe HL, sa longueur, et la signification des différents compteurs, nous avons désassemblé la routine en langage machine traitant KL-ADD-TICKER. Ce vecteur envoie dans la ROM du système d'exploitation à l'adresse &01B3 : 01B3 E5 KLADTI : PUSH HLAprès sauvegarde dans la pile de l'adresse de début du bloc (PUSH HL), HL est incrémenté deux fois (INC HL). |
Nos caractères, une fois lus et vérifiés en conformité, il faudra les diriger vers le port CENTRONICS de l'imprimante, si celle-ci n'est pas considérée comme occupée. Le test sur sa broche BUSY (OCCUPE) peut être effectué grâce au vecteur MC-BUSY-PRINTER à l'adresse RAM &BD2E (Partie 4, chapitre 2.7, page 62). Aucune information n'est à fournir en entrée. Au retour vous connaîtrez l'état occupé si l'indicateur CARRY est positionné à 1.
L'indicateur CARRY positionné à zéro nous permettra d'imprimer le caractère lu grâce au vecteur MC-SEND-PRINTER situé en &BD31 (Partie 4, chapitre 2.7, page 63). Le seul paramètre requis est le code ASCII du caractère contenu dans le registre A.
Nous vous proposons ci-dessous l'algorithme de l'impression d'un caractère que vous pourrez réutiliser dans n'importe quel algorithme :
Ce qui donne l'ordinogramme suivant :
A partir de ces ordinogrammes, nous pouvons écrire le programme de traitement de l'interruption. Il reste tout de même une dernière chose à définir : les paramètres de l'interruption EVENT (priorité, valeur initiale du compteur, valeur de réarmement du compteur...).
Nous avons choisi pour le compteur une valeur hexadécimale de &99, ce qui nous donnera une période d'appel de la reconnaissance de l'appui sur < CONTROL > et < 1 > de :
Le programme Assembleur complet est le suivant :
L'initialisation de l'interruption s'effectue aux adresses &A000 à &A00B.
Suivent la réservation de deux zones mémoires : 6 octets pour les compteurs et l'adresse de chaînage, et 7 octets pour les caractéristiques de l'interruption.
Aux adresses &A019 à &A025 se trouve la routine permettant le chaînage de l'interruption et l'initialisation des compteurs, c'est en parcourant cette routine que l'interruption devient opérationnelle.
Les adresses &A026 à &A02C contiennent les codes machine Z80 de la routine permettant de désactiver l'interruption.
De &A02D à &A046 nous trouvons les codes de la routine permettant de reconnaître l'appui simultané sur les touches <CONTROL> et <1>. Les lignes de pseudo-codes à modifier pour adapter le programme au CPC 464 se trouvent en 27 et 29, pour modifier les contenus des adresses &A032-&A033 et &A039-&A03A.
Lorsqu'une impression est demandée, on se branche à l'adresse &A047 qui exécute la copie d'écran proprement dite.
De &A047 à &A053 sont effectués la recherche de la position du curseur, sa sauvegarde et le numéro de la dernière colonne, qui est augmentée de 2 pour le compteur.
En &A056, le compteur de ligne est initialisé à la première ligne.
&A058 à &A05F permettent de positionner la tête de l'imprimante à la gauche de la ligne suivante.
&A064 initialisé le compteur de colonne en première position.
Entre les lignes &A066 et &A069, le curseur est positionné, puis le caractère lu (&A06D).
Viennent ensuite différents tests sur la validité du caractère (il faut qu'il soit compris entre &20 et &7F), puis son impression (&A080).
La colonne est ensuite incrémentée, on vérifie si c'est la dernière (&A08B), sinon, on remonte en &A066, sinon, la ligne est incrémentée. Si plus de 25 lignes sont atteintes, il faut restaurer le curseur (&A0A2 à &A0A5), sinon on recommence pour la ligne suivante en &A058.
Aux adresses &A0A9 à &A0B9 se trouvent les codes de la routine d'impression d'un caractère ASCII contenu dans le registre A.
Les trois dernières adresses sont réservées pour les variables de sauvegarde : position du curseur et numéro de la dernière colonne.
Si vous désirez utiliser cet utilitaire sans vous servir d'un logiciel d'assemblage, nous vous proposons ci-dessous le programme Basic permettant de placer en mémoire les codes machines Z80.
Les explications pour l'installation et la sauvegarde sont données dans le programme.
Après installation, il vous suffit d'initialiser l'interruption par CALL &A000. A partir de maintenant, la routine est prête à être activée, mais ne fonctionne pas encore.
Vous l'activerez par CALL &A019. Assurez-vous que votre imprimante est correctement connectée, puis maintenez appuyées à tout moment les touches < CONTROL > et < 1 > (pas f1 !) au moins 3 secondes, pour avoir une copie texte de l'écran.
Si vous ne désirez pas que l'appui sur les deux touches citées n'agissent de cette façon et que vous leur réservez un tout autre usage, il suffit de frapper la commande CALL &A026.
Vous pourrez à un autre moment, réactiver l'interruption, à moins que vous ne désirez récupérer la place mémoire utilisée par le traitement.
Comment sont traitées les interruptions
Nous vous proposons de découvrir une partie de la gestion des interruptions dans votre CPC. Il n'est pas ici question d'entrer dans le détail du logiciel de base Ile moniteur) en ROM permettant le traitement, mais d'avoir un aperçu du déroulement, pour le débutant en langage machine — nous fournissons aux initiés une large partie du désassemblage, afin qu'ils assouvissent rapidement leur soif de découverte — nous fournirons tout de même un algorigramme permettant de sentir l'ordre d'exécution des interruptions (FAST TICKER - FRAME FLY - TICKER).
Nous savons qu'une seule interruption est déclenchée sur le Z80 au niveau matériel. Celle-ci renvoie à l'adresse &0038, où est effectué un branchement en &B941 (en RAM). A partir de cet endroit, les registres sont sauvegardés, une commutation de la ROM inférieure est effectuée, et le programme est envoyé à l'adresse &00B1 du moniteur (dans le cas du CPC-6128).
Nous vous fournissons ci-dessous nos investigations concernant le désassemblage du sous-programme déterminant l'ordre de traitement des trois types d'interruptions, entre les adresses &00B1
A partir du &00B8, on effectue une lecture, dans le registre A, du port B du composant d'interfaçage parallèle PIO 8255 (à l'adresse &F5XX). Sur ce port, le bit 0 va nous intéresser : il correspond à l'état de la broche V-SYNC du CRTC, ou se trouve le signal de synchronisation verticale du faisceau de balayage écran.
Afin d'interroger rapidement cet état, on effectue une rotation vers la droite du registre A (RRA), ce qui a pour effet de placer le bit 0 dans l'indicateur de retenue (Carry). Si CARRY est nul, alors le balayage écran n'est pas terminé, on saute donc le traitement de FRAME FLY (JR C,00C7).
Sinon, le traitement de FRAME FLY est effectué entre les adresses &OOBF et &OOC6. On charge le contenu de l'adresse de base du bloc d'interruption (LD HL,(B8B9)). Si on y trouve une valeur différente de zéro (LD A,H - OR A) alors on saute au traitement de la file d'attente en &0153H (CALL NZ,0153).
Si aucun événement de type FRAME FLY n'est présent, on étudie FAST TICKER. (On s'aperçoit ici que FRAME FLY est prioritaire par rapport à FAST TICKER, mais cela n'apparaît qu'une fois tous les 50e de seconde alors que FAST TICKER apparaît tous les 300e de seconde.) Le traitement de FAST TICKER débute donc en &00C7 jusque &00CE.
De la même façon que pour FRAME FLY, le contenu de l'adresse de base est évalué (LD HL,(&B8BB)) par rapport à zéro (LD A,H - OR A) et le traitement de la file d'attente effectué si non nul (CALL NZ.0153).
On passe ensuite au traitement d'une autre file d'attente importante aussi sur CPC, celle de la queue sonore située en &20D7, par CALL 20D7.
A l'adresse &00D2, le compteur permettant de gérer les événements simples est traité (LD HL,B8BF - DEC (HL)), puis testé (RET NZ).
Si ce compteur a atteint la valeur nulle, il est restauré (LD (HL),06), puis l'état du clavier est pris en compte par l'envoi au vecteur du sous-programme de traitement (CALL BDF4).
Arrive ensuite le traitement de la chaîne des blocs concernant TICKER, à l'adresse &00DC.
Le contenu de l'adresse de base est évalué, pour quitter le traitement des interruptions s'il est nul (LD HL,B8BD - LD A,H - OR A - RET Z).
S'il y a chaînage, une adresse mémoire sert de drapeau pour traitement ultérieur et gestion des compteurs : (LD HL,B831 - SET 0,HL) et on retourne en RAM pour la suite du traitement de l'interruption sur &0038 (RET).
Afin d'imager ces explications, nous vous proposons ci-dessous l'algonigramme simplifié du programme précédemment explicité :
:
Nous vous laissons, si vous le désirez, pousser vos investigations en vous orientant sur les adresses intéressantes de la ROM inférieure :
Page précédente : 4/2.11 III - Les interruptions logicielles (SOFT) |
|
Page créée en 047 millisecondes et consultée 370 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. |