CODINGAMSTRAD CPC 464 - CRÉER DE NOUVELLES INSTRUCTIONS

Nouvelles Instructions 004

EXEMPLES DE PROGRAMMES

1. PAUSE DE X SECONDES

Nous allons, pour votre baptême du feu, nous attaquer à un programme bien modeste, puisqu'il ne comprend que 23 octets. Il permettra d'effectuer des pauses de longueur variable, et remplacera avantageusement les boucles de temporisation laborieuses et imprécises que l'on est obligé d'utiliser sur l'Amstrad.

Ce programme débute à l'adresse 43880, finit en 43902 (chiffre de vérification : 2976), est relogeable (ce qui veut dire que l'on peut l'implanter ailleurs en mémoire si l'on veut ce qui n'est pas le cas de tous les programmes, nous le verrons plus tard), et son format d'appel est le suivant :

CALL 43880,X

Le paramètre X détermine, en secondes, la longueur de pause désirée. Voici les conventions de la présentation du listing : La première colonne indique des numéros de ligne qui ne servent à rien d'autre qu'aux explications. La deuxième indique l'adresse du premier octet du code machine de cette ligne (cette adresse est également fournie en hexadécimal si, pour une raison ou pour une autre, elle est remarquable). La troisième colonne, sans titre, sert à visualiser les sauts éventuels. La quatrième indique les instructions du programme (en hexadécimal, bien sûr), et la cinquième les mnémoniques de ces mêmes instructions (les mnémoniques sont simplement des représentations symboliques des différentes instructions, dont il est plus facile de se souvenir que des codes machine).
Rappelez-vous enfin que toutes ces instructions sont décrites en détail, le cas échéant avec leurs variantes, dans la Cinquième Partie. N'hésitez pas à vous y reporter si besoin est.

Le principe de ce programme est exactement le même que celui d'une boucle de temporisation en BASIC : nous allons demander à l'ordinateur... de ne rien faire, mais un grand nombre de fois, pour faire "passer le temps".
En réalité, nous nous servirons de deux boucles, pour une* raison que vous comprendrez plus loin. Nous allons tout d'abord nous intéresser à la boucle constituée par les lignes 5 à 9, qui dure exactement une demi-seconde :

Ligne 5

Chargement du registre HL avec le nombre 65110 (&FE56). Vous remarquerez qu'après le code de chargement (&21), on met d'abord l'octet faible de la valeur à charger, et ensuite l'octet fort (signalons également que pour charger un registre double, l'octet fort doit toujours être indiqué, même s'il est égal à 0). Pourquoi ce nombre 65110 ? Il a été déterminé par essais successifs, de manière que cette boucle centrale dure une demi-seconde (à quelques millièmes près).

Ligne 6

Décrémentation du registre HL, ce qui signifie que l'on enlève 1 au contenu de ce registre.

Ligne 7

Chargement du registre A (ou accumulateur) avec le contenu du registre H (donc avec l'octet fort du contenu de HL).

Remarque

Le contenu de H n'est pas modifié après l'instruction. D'une manière générale, les instructions de chargement n'affectent jamais le contenu de la source.

Ligne 8

Littéralement "Exécution d'un OU logique entre le registre L et le registre A". Il faut savoir que le résultat d'un OU logique entre un registre et l'accumulateur n'est égal à 0 que si le contenu de ces deux registres est égal à 0.
Comme A est chargé avec le contenu de H, c'est exactement comme si nous faisions un OU logique entre H et L (ce qui n'est pas possible directement). Cette ligne 8 aura donc pour résultatO quand et seulement quand H et L seront égaux à 0, donc quand HL sera vide.
Elle signifie "Saut relatif de –5 si non nul", c'est-à-dire tant que l'indicateur Z (voir Première Partie, section 5) n'est pas mis, signalant que l'opération qui vient d'avoir lieu (le OU logique) avait pour résultat 0.
Pour résumer, le saut aura lieu tant que HL ne sera pas vide (saut de -5, donc en ligne 6 ; voir à ce sujet l'Annexe I qui explique tout sur les sauts relatifs). Si HL est vide, le saut sera ignoré et le programme se poursuivra en ligne 10.
La boucle est donc bouclée : en ligne 6, HL est à nouveau décrémenté, puis A est chargé avec H, le OU logique effectué, et ainsi de suite, jusqu'à ce que HL ait été décrémenté 65110 fois. L'ensemble est donc exécuté en une demi-seconde, ce qui prouve bien la rapidité du langage.
Il reste maintenant à étudier la boucle générale.
Nous avons dit que, lors de l'appel du sous-programme, le paramètre X était sensé exprimer un temps en secondes. Or, notre boucle centrale ne fait qu'une demi-seconde. La première chose qu'il y a donc à faire, est de multiplier le paramètre X par 2 :

Ligne 1

Si vous avez bien lu la section "Les paramètres transmissibles", cette ligne ne devrait pas poser de problème : chargement du registre H avec le contenu de l'emplacement mémoire d'adresse IX+1, c'est-à-dire avec l'octet fort de X.

Ligne 2

Chargement du registre L avec le contenu de l'emplacement mémoire d'adresse IX+ 0, c'est-à-dire avec l'octet faible de X. Après ces deux lignes, HL est donc chargé avec X.

Lignes 3

Addition de HL... avec lui-même ! Le résultat étant chargé dans HL, cela revient donc à multiplier par 2 son contenu. Il est maintenant chargé avec 2 * X.

Ligne 4

Empilement du registre HL : le contenu du registre HL est déposé sur la fameuse pile évoquée dans la Première Partie. Le registre HL va en effet être utilisé pour autre chose, mais nous aurons encore besoin de son contenu, que nous stockons donc en le déposant sur la pile.
Remarque importante
Lorsque l'on empile un registre, celui-ci ne se vide pas, contrairement à ce que l'on pourrait croire. Après cette ligne 4, par exemple, HL contient toujours X * 2. L'empilement provoque en quelque sorte un recopiage de la valeur sur la pile.
Après cette ligne, le programme arrive à la ligne 4, où commence la boucle centrale déjà étudiée. Cette boucle est exécutée, après quoi le programme passe à la ligne 10.

Ligne 10

Dépilement du registre HL : la donnée sauvegardée en ligne 4 est retirée de la pile et chargée dans le registre HL, qui contient donc maintenant à nouveau X * 2.

Lignes 11,12, 13

Elles suivent exactement le même processus que les lignes 6, 7 et 8 déjà étudiées : décrémentation de HL, chargement de A avec H, OU logique entre A et L. Comme vous l'avez sans doute déjà compris, il s'agit là de notre boucle générale, ou tout au moins de sa partie compteur.

Ligne 14

Saut relatif de -15 (en ligne 4) si non nul : ni HL n'est pas encore égal à 0, le programme saute en ligne 4 où le contenu actuel de HL est de nouveau "mis au frais". Ensuite, nouveau départ de la boucle centrale pour une demi-seconde.
L'ensemble du processus se renouvellera (X * 2) fois, et comme la boucle centrale dure une demi-seconde, le temps total sera bien de X secondes. Lorsque le compteur de la boucle générale atteint 0, le saut n'est pas effectué et le programme passe à la ligne 15.

Ligne 15

Cette instruction signale la fin du programme en langage machine et provoque le retour au BASIC.
Le programme doit être implanté selon les principes exposés dans la Deuxième Partie et peut être ensuite appelé à partir du BASIC :

100 CALL 43880,10

Cette ligne BASIC provoquera une pause de dix secondes.
Signalons qu'il est facile de modifier le programme pour que le paramètre X détermine un temps exprimé en fractions de seconde. Il suffit pour cela de jouer sur la valeur que l'on charge dans HL à la ligne 5 (avec une valeur de 6290, par exemple, un CALL 43880,1 provoquera une pause de 1/10 de seconde).
En procédant par tâtonnements, on peut ainsi trouver n'importe quelle unité de pause. Il faut bien sûr pour cela utiliser l'instruction BASIC TIME :

100 TE = TIME/300 : CALL 43880,1 : TE1 = TIME/300 : PRINTTE1-TE

Le temps de pause s'affichera en secondes.

★ ANNÉE: ???
★ AUTEUR: JEAN-CLAUDE DESPOINE

Page précédente : Nouvelles Instructions 003
Je participe au site:

» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.7-desktop
Page créée en 415 millisecondes et consultée 1268 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.