| ★ CODING ★ AMSTRAD CPC 464 - CRÉER DE NOUVELLES INSTRUCTIONS ★ |
| Nouvelles Instructions 008 |
EXEMPLES DE PROGRAMMES5. DESSIN D'UN CERCLE Ce programme est certainement l'un des plus complexes de tous ceux que présente cet ouvrage, essentiellement parce que nous allons y manipuler des variables de deux types : entières ou à virgule flottante. A cet égard, il est indispensable d'avoir lu au préalable l'Annexe V, ou tout au moins sa première partie (Les variables numériques). CALL 43680,XC,YC,R,C,PV
Par ailleurs, une protection sera établie, qui provoquera un retour immédiat au BASIC si l'instruction CALL n'est pas suivie de quatre ou cinq paramètres. Avec certains programmes, en effet, l'oubli d'un ou de plusieurs paramètres peut provoquer des catastrophes. Ce genre de protection permet d'éviter ces désagréments. Vous savez certainement que l'équation d'un cercle se présente sous la forme : X - XC + R * Cos(a) Y = YC + R * Sin(a)la valeur a étant la valeur de l'angle qui varie de 0 à 360 degrés. Nous allons donc utiliser dans ce programme les routines &BD8B et &BD88 permettant de calculer respectivement les sinus et les cosinus. Ces routines sont malheureusement assez lentes et c'est pour gagner du temps que nous allons utiliser une petite astuce grâce à laquelle nous n'aurons à calculer que les sinus et cosinus des angles allant de 0 a 90 degrés au lieu d'avoir à le faire de 0 à 360 degrés. La figure ci-dessous servira à expliquer le processus :
Chaque fois que nous aurons calculé les coordonnées d'un point (X,Y), dont l'angle correspondant variera de 0 à 90°, nous calculerons les coordonnées relatives par rapport à ce point du point (X1, Y1), puis les coordonnées relatives de (X2,Y2) par rapport à (X1.Y1), et enfin les coordonnées relatives par rapport à (X2,Y2) de (X3,Y3). Les quatre quadrants seront donc dessinés simultanément. Remarquons que les coordonnées relatives de : (X1,Y1) par rapport à (X,Y) sont : - 2 (X - XC), 0 ;A ce sujet, revoir éventuellement l'Annexe II. Il faut enfin savoir que nous aurons, au cours de ce programme, à stocker provisoirement un certain nombre de variables. C'est la raison pour laquelle les cases mémoires 43878 à 43895 sont divisées en cinq "placards" dans lesquels nous rangerons ces variables (voir en fin de listing la manière dont sont disposés ces placards). Voyons maintenant le déroulement ligne par ligne de ce programme (dans un premier temps, nous laisserons de côté les lignes 1 à 17, qui rendent le cinquième paramètre optionnel et installent la protection' évoquée plus haut). Considérons donc pour l'instant que le programme débute en ligne 18, et qu'il n'y a que quatre paramètres derrière notre instruction CALL (XC,YC,R,C). Le cercle tracé sera donc vide.
Le tableau suivant représente les cinq placards :
Intéressons nous tout d'abord au bloc constitué par les lignes 18 à 37 qui se charge d'effectuer le calcul de l'abscisse X (rappelons que x ft XC + R * Cos (a)). Ligne 18 : Le contenu du registre IX est rangé dans le placard prévu à cet effet (cases mémoire 43893 et 43894). Ce registre est chargé pour l'instant, comme nous le savons, avec l'adresse de l'octet faible de C, mais les routines Sinus et Cosinus que nous appellerons plus loin utilisent ce registre pour leur propre compte et vont donc dénaturer son contenu, c'est pourquoi il faut le sauvegarder. Ligne 19 : Chargement de l'accumulateur avec 90. Ce chiffre servira à la fois pour initialiser le compteur, et pour calculer les sinus et cosinus successifs des angles 90 à 0. Ligne 20 : Le contenu de A est rangé dans son placard (case mémoire 43895). Une seule case suffit car la machine "sait" que le contenu de A ne peut en aucun cas être supérieur à 255. Lignes 21 et 22 : Chargement de A avec le numéro de couleur choisi et appel de la routine &BBDE, qui fixe la couleur graphique. Lignes 23 et 24 : Chargement de HL avec R. Ligne 25 : Chargement de DE avec l'adresse de la première des cinq cases constituant le placard réservé au rayon R. Nous allons en effet transformer la représentation de R (qui est pour l'instant stockée sous une forme entière, c'est-à-dire sur 2 octets) en sa représentation en virgule flottante, donc sur 5 octets. Nous y sommes obligés car nous allons travailler avec le bloc de routines "Arithmétique avec virgule flottante". Ligne 26 : Appel de la routine &BD40 : "Transformer la représentation entière d'un nombre en sa représentation en virgule flottante". Le nombre traité doit au départ être chargé dans HL et l'adresse du placard où l'on veut qu'il se retrouve doit être chargée dans DE. Après l'exécution de cette ligne, la représentation en virgule flottante de R est donc rangée dans les cases mémoire 43878 à 43882. Ligne 27 : Chargement de HL avec le contenu de 43895, c'est-à-dire avec la valeur de l'angle à ce moment : 90 au premier tour de boucle, 89 au deuxième, 88 au troisième, etc. Ligne 28 : Chargement de DE avec l'adresse du placard réservé aux cosinus (on peut également dire : pointage de DE sur ce placard). Ligne 29 : Comme pour le rayon, transformation en virgule flottante et rangement du résultat au placard. Il faut savoir qu'au retour de la routine &BD40, les contenus des registres HL et DE ne sont plus les mêmes. Au cours de ses manipulations, la routine les modifie et, après son exécution, c'est maintenant HL, et non plus DE, qui est chargé avec l'adresse du placard. Ligne 30 : Appel de la routine &BD8B qui calcule le cosinus d'un angle. Registre d'appel: HL doit être chargé avec l'adresse de la variable que l'on veut traiter (ce qui était bien le cas après la ligne 29). Registre de réponse : HL reste inchangé. Le résultat est rangé à la place de la variable. Ligne 31 : Chargement de l'adresse du rayon R dans DE, en prévision de l'utilisation de la routine &BD61 en ligne 32. Ligne 32 : Appel de la routine &BD61 qui effectue la multiplication de deux nombres. Ligne 33 : Appel de la routine &BD45, qui effectue l'opération inverse de la routine &BD40, puisqu'elle transforme une représentation en virgule flottante en une représentation entière. Ligne 34 : Chargement de IX avec le contenu de l'emplacement mémoire d'adresse 43893. Ce registre est donc maintenant rechargé avec sa valeur initiale sauvegardée en ligne 18. Ligne 35 : Une ligne un peu particulière : il s'agit de l'appel du sous-programme interne d'adresse 43864 (lignes 78 à 80). Ce sous-programme a pour fonction de charger DE avec XC. Nous aurons en effet besoin d'effectuer plusieurs fois cette opération, et il est donc rentable de faire un sous-programe spécifique qu'il suffit d'appeler. Ce sous-programme est extrêmement simple : Lignes 78 et 79 : Chargement de DE avec XC Ligne 80 : Retour de sous-programme (donc à la ligne 36) Plusieurs remarques s'imposent néanmoins :
Le résultat de cette addition se trouve dans HL. Ligne 37 : Mise au placard de ce résultat. Notons qu'il s'agit d'un entier, maintenant, et qu'il est donc rangé sur 2 octets : 43883 et 43884.
Il est donc inutile de refaire une étude ligne par ligne de ce bloc chargé de calculer YC + R * Sin(a), et nous nous contenterons de résumer la situation après son exécution (donc immédiatement après la ligne 47):
Ligne 48 : Chargement de DE avec X. Lignes 49 à 50 : Sauvegarde, en les rangeant sur la pile, de Y puis de X (attention à la pile, ça va se compliquer...). Ligne 51 : Appel de la routine &BBEA qui dessine sur l'écran le point de coordonnées X,Y. Ligne 52 : Chargement de DE avec XC. Ligne 53 : Appel du sous-programme interne d'adresse 43850, allant des lignes 69 à 77. Voyons ce que fait cette routine : Lignes 69, 70 et 71, ou "l'art et la manière d'éviter un énorme piège". En effet, qu'y a-t-il sur la pile au moment où l'on arrive à la ligne 69 ? X ? Eh bien non, justement. N'oubliez pas que, lorsque le programme rencontre un appel de sous-programme, l'adresse de retour est empilée et ne sera dépilée qu'au moment du retour. Au sommet de la pile se trouve donc pour l'instant l'adresse 43820. Cette adresse est soulevée, X qui est en-dessous est chargé dans HL, puis l'adresse est reposée sur la pile. Ligne 72 : DE est soustrait de HL. Le résultat (X - XC) se retrouve dans HL. Ligne 73 : HL est additionné à lui-même, ce qui revient à le multiplier par 2. HL contient maintenant 2 (X – XC). Ligne 74 : Appel de la routine de changement de signe déjà étudiée. HL est maintenant chargé avec – 2 (X – XC). Ligne 75 : Echange des contenus de HL et DE. Ligne 76 : HL est chargé avec 0. Ligne 77 : Retour de sous-programme. Rappelons encore une fois que l'adresse de retour est en même temps dépilée. Lignes 54, 55, 56 : Sauvegarde de – 2 (X – XC), en s'arrangeant pour que Y reste au sommet de la pile. Ligne 57 : HL étant toujours chargé avec 0 et DE avec – 2 (X – XC), appel de la routine &BBED qui dessine un point à une position relative au curseur graphique, ce dernier se trouvant alors en (X,Y), c'est-à-dire au dernier point tracé. Ligne 58 : Appel du sous-programme interne d'adresse 43871 qui charge DE avec YC. Ligne 59 : Appel du sous-programme interne d'adresse 43850, déjà étudié à la ligne 53. Cette fois, il va calculer - 2 (Y – YC). Au retour, HL est chargé avec 0 et DE avec - 2 (Y - YC). Ligne 60 : Inversion de HL et D. Cette fois en effet, c'est l'abscisse qui doit être égale à 0. Ligne 61 : Appel de la routine &BBED, déjà étudiée. Notre troisième point étant tracé, reste le quatrième, de coordonnées relatives 2 (X – XC), 0. Ligne 62 : Si vous avez bien suivi l'état de la pile, vous savez qu'il s'y trouve actuellement au sommet la valeur – 2 (X - XC), sauvegardée en ligne 55. La ligne 62 charge cette valeur dans HL. Ligne 63 : Appel du sous-programe interne d'adresse 43856 (ligne 74). Notons que ce programme est en partie le même que celui qui est appelé aux lignes 53 et 59. Ligne 64 : Tracé du quatrième point (X3.Y3). Ligne 65 : HL est chargé avec l'adresse du placard Angle. Ligne 66 : Une nouvelle instruction : "Décrémenter le contenu de l'emplacement mémoire adressé par HL." L'angle est donc diminué de 1. Ligne 67 : Encore une nouvelle instruction : "Retour conditionnel de sous-programme." Si le résultat de l'opération de la ligne 66 est inférieur à °. alors le retour au BASIC est effectué, sinon le programme se poursuit en séquence. Ligne 68 : Saut relatif de –106 (en ligne 27). Le programme va ainsi boucler )Usqu'à ce que toutes les valeurs de l'angle, de 90 à 0, aient été traitées. Lignes 69 à 77 : Calcul de -2(X - XC) ou -2(Y - YC). Lignes 78 à 80 : Chargement de DE avec XC. Lignes 81 à 83 : Chargement de DE avec YC. Détaillons tout d'abord la procédure qui va nous permettre de dessiner un cercle plein. 1. Tracé du point (X,Y).Mais que se passerait-il si l'on y apportait les modifications suivantes : 1. Tracé du point (X,Y).Eh bien, tout simplement ceci :
En procédant ainsi, les lignes tracées les unes contre les autres, au fur et à mesure que a varie de 90 à 0, formeront un cercle plein. Le point (X1,Y1) est tracé en ligne 57 grâce à la routine &BBED et le point (X3.Y3) en ligne 64 grâce à la même routine. Il suffirait donc de remplacer cette routine &BBED par la routine &BBF9 qui trace une ligne de la position du curseur jusqu'à la position relative indiquée. Les lignes 57 et 64 se situent en mémoire comme ceci : 43823 : CD ;43840 : CDOn peut donc se contenter de charger les cases mémoire 43824 et 43841 avec &F9 pour obtenir un appel non plus à &BBED, mais à &BBF9 |
| ![]() |
| Page précédente : Nouvelles Instructions 007 |
|
Page créée en 740 millisecondes et consultée 1429 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. |