CODING ★ INITIATION A L'ASSEMBLEUR - CPC n°14 ★

Initiation à l'assembleur (CPC Revue n°14)

Nous continuons cette série d articles par un autre exemple de programme écrit en assembleur. Nous avons choisi ce mois-ci un jeu classique, le tennis, qui fut le premier des jeux vidéo. Il aurait pu être écrit différemment, mais le choix s'est porté sur ce type de programmation afin de faciliter la compréhension du programme pour le débutant.

Pour cela, nous avons fait abondamment appel aux sous-programmes de la ROM de l'AMSTRAD en utilisant toujours les points d'entrée en RAM. Dans ce jeu, l'écran présente un cadre à trois côtés sur lesquels la balle va rebondir ; il faudra rattraper cette balle avec une raquette qui se déplace en bas de l'écran horizontalement et qui est actionnée par les flèches du clavier. Toute autre touche pourra être choisie. Tous les paramètres peuvent être modifiés aisément, que ce soit la vitesse de déplacement de la raquette ou la vitesse de déplacement de la balle, ces paramètrès étant définis dans la zone des variables. Pour une partie vous disposez de 10 balles, chaque frappe de la balle avec la raquette rapporte un point. Analysons la structure de ce programme. Nous l'avons décomposé en quatre blocs :

– un bloc de déclaration d'équivalence,
– un bloc de déclaration de variable,
– un bloc de sous-programme,
– le programme principal.

Tout d'abord, nous trouvons la directive ORG qui fixe l'adresse de départ du pro gramme. Pour une utilisation de ZEN, on trouve une autre directive LOAD indiquant au programme d'assemblage où il devra loger le code en mémoire. Le premier bloc de notre programme est un bloc d'équivalences qui attribue un nom aux différents sous-programmes de la ROM que nous allons appeler. Nous choisirons des étiquettes à chacune de ces adresses afin de ne pas être obligés de rechercher à chaque fois les adresses dans la documentation et aussi afin de faciliter la relecture du programme II est à noter que la plupart de ces routines détruisent tout ou une partie des registres du Z80 aussi, dans ce programme, nous travaillerons assez peu avec les registres sauf, bien sûr, pour les appels aux sous-programmes pour lesquels ils ont une fonction bien précise. Nous avons mis ensuite les variables uti lisées en début de mémoire. Si nous voulons que l'adresse de lancement reste en 200H, qui est la valeur fixée par le ORG., nous mettrons un saut par dessus cette zone de variable.
Les variables que nous utiliserons sont : XR qui contient la position de la raquette à l'affichage.
XRP qui est la coordonnée de la position précédente de la raquette après un déplacement. La mémorisation de cette coor donnée raquette nous permet d'effacer le dessin de la raquette après un dépla cernent.

YB et YB sont les coordonnées de la balle visualisée sur l'écran. XBP et YBP sont les coordonnées de la balle précédant un déplacement. Ces variables sont de type word, c'est-à-dire sur 16 bits, car elles peuvent prendre des valeurs jusqu'à 640 et un octet, rappelons-le, prend comme valeur maxi maie 255.

SENS est une variable de type octet qui permet à tout moment, dans le programme, de connaître le sens de déplacement de la balle ; elle peut prendre les valeurs 1, 2, 3, 4 qui correspondent aux quatre sens possibles suivant les deux diagonales, c'est-à-dire le sens 1 correspond à une balle descendant à droite, le sens 2 à une balle montant à droite, le sens 3 à une balle montant à gauche, le sens 4 à une balle descendant à gauche. CPT est une variable de type octet servant de compteur pour le score ; son contenu est particulier puisque ce score est codé en BCD, nous expliquerons cela plus loin.
VITB est une variable sur 16 bits qui contient l'incrément du déplacement de la balle et par conséquent correspond à la vitesse de son déplacement. VITR reste une variable identique à VITB mais affectée au déplacement de la raquette.
NBB est une variable initialisant le nombre de balles.

Ensuite, vient une série de sous-programmes. Ces sous-programmes sont construits autour d'une fonction particulière à l'intérieur du jeu. Ils peu vent utiliser des variables ou des paramètres qui pourront leur être envoyés au travers de registres ou au travers de variables communes. Le premier, ECRAN, comme son nom l'indique, va initialiser l'écran ; pour cela, il appelle le sous programme de la ROM qui positionne en mode d'affichage et qui met l'écran dans le mode contenu dans le registre A, ici 1. Il initialise ensuite les encres ; on utilise ici le numéro d'encre 0 qu'on initialise à la couleur 0, soit le noir, et le numéro d'encre 1 qu'on initialise à la couleur 13. Ces encres sont ensuite affectées au fond et au stylo et le bord est mis dans la couleur 0, tout ceci comme en Basic. Les registres utilisés l'ont été en fonction des spécifications des sous-programmes appelés. Ce sous-programme se termine par une réinitialisation de la vitesse de répétition du clavier et du temps d'attente avant cette répétition. Le registre H contient le nombre de fois 1/50° de seconde d'attente et le registre L contient le nombre de scrutations effectuées par seconde, 1 correspond à 50, 2 à 25, etc. Le sous-programme CADRE trace le cadre ou les murs entourant notre jeu ; il n'y a pas de mur derrière la raquette. Il appelle les routines système correspondant au MOVE BASIC et au DRAW, ces routines recevant les coordonnées en abscisse à travers la paire de registres DE et les coordonnées en ordonnée à travers la paire de registres HL. Le sous-programme RAQUETTE trace la raquette ; ce tracé est effectué en utilisant les routines graphiques de la ROM équivalentes à MOVER et DRAWR du Basic. Les tracés sont donc effectués en relatif par rapport au dernier point, les coordonnées comme pour les sous-programmes DRAW et MOVE se trouvent dans les paires de registres DE et HL. Dans notre jeu, la raquette est constituée par deux lignes horizontales de longueur 35, la valeur hexadécimale OFFDDH correspond à la valeur signée -35.

Le sous-programme TBALL effectue le dessin de la balle ; dans ce sous-programme, nous avons choisi un autre mode de passage des paramètres . la balle est tracée en coordonnées absolues passées dans les registres DE et HL. Ces registres sont sauvegardés dans la pile par des PUSH car le sous-programme PLOT les détruit. Le dessin de la balle est fait à partir de points placés en croix. Le sous-programme SCORE sert à l'affichage du score. Il incrémente à chaque appel la variable CPT et l'affiche à l'écran sur la ligne 2 en colonne 19. Dans ce sous-programme, nous voyons apparaître une nouvelle instruction DAA que nous allons expliquer.

LA REPRESENTATION DCB ET L'INSTRUCTION DAA

Jusqu'à présent, nous avons vu qu'un nombre pouvait être représenté en binaire, soit signé, soit non signé. Il existe une autre méthode de représentation des nombres qui est plus proche de notre système décimal, c'est la représentation décimale codée binaire. Dans cette représentation, chaque chiffre décimal est codé séparément en binaire, mais voyons tout de suite un exemple. Le nombre décimal 25 se représente en binaire pur sous la forme . 00011001 116H). Il se représentera en DCB : 00100101. Nous avons dissocié notre octet en deux sous-ensembles de quatre bits que nous pouvons appeler quartets. Comme vous le savez, pour représenter un nombre de 0 à 9, il est nécessaire de disposer de 4 bits et donc avec un octet, nous allons pouvoir représenter deux chiffres décimaux, mais attention, les règles de l'addition binaire telles que nous les avons vues, ne pourront plus s'appliquer directement à cette nouvelle représentation. Lorsque nous ferons une addition ou une soustraction entre deux nombres en DCB, il va être nécessaire d'effectuer ensuite un ajustement du résultat et ce sera le rôle de l'instruction DAA qui est l'instruction d'ajustement décimal de l'accumulateur. Nous avons une application de cette représentation dans notre programme : le score est compté en DCB et il n'est donc plus nécessaire de faire une conversion pour l'afficher, il suffit de récupérer chaque chiffre en prenant chaque quartet séparément. Ceci nous ramène à notre sous-programme, l'affichage se fait en prenant le chiffre de poids fort, pour cela, nous effectuons quatre décalages logiques à droite, ce qui ramène ce chiffre dans les poids faibles de l'accumulateur, on y ajoute 30H pour le coder en ASCII et on l'envoie au sous-programme d'affichage. Le chiffre de poids faible est récupéré en masquant par un ET logique le chiffre de poids fort et affiché par la même méthode.

LES OPERATIONS DE DECALAGE

Dans une opération de décalage, le contenu du registre est décalé vers la gauche ou vers la droite d'une position binaire. Le bit qui entre est mis à 0 et le bit qui sort est mis dans le drapeau de carry C. Il y a une exception pour le décalage arithmétique à droite : lorsque le bit le plus à gauche est à 1, après une opération de décalage à droite, ce bit est recopié dans la position la plus à gauche. Nous avons deux types de décalages :

des décalages logiques et des décalages arithmétiques , le décalage logique à gauche correspond à la multiplication par deux en arithmétique non signée et le décalage à droite à l'opération de division par deux, toujours en arithmétique non signée. Les décalages arithmétiques correspondent aux mêmes opérations, mais en arithmétique signée d'où la nécessité, dans le décalage arithmétique à droite, de maintenir le signe dans le bit le plus à gauche.

Nous arrivons maintenant au programme principal.

Il commence par une initialisation du registre pointeur de pile, le registre SP. On initialise ensuite l'écran par l'appel à ECRAN et à CADRE vus plus haut. Ce programme principal se compose d'une boucle correspondant à une balle, cette boucle sera donc exécutée 10 fois, elle débute à l'étiquette LANCE. La balle arrive dans le jeu par le haut de l'écran avec une abscisse aléatoire. Le nombre aléatoire est obtenu en venant lire le registre de rafraîchissement du Z80 que l'on appelle R. Les coordonnées de la nouvelle balle sont alors initialisées, le score et le nombre de balles restantes sont affichés. La raquette est dessinée aux coordonnées (XR,1 51 après avoir été effacée des coordonnées précédentes. Le clavier est scruté sans attendre qu'une touche soit frappée et la routine KEY positionne le drapeau de CARRY lorsqu'une touche a été actionnée. Si aucune touche n'a été actionnée, le programme passe au mouvement de la balle, sinon il teste quelle touche a été appuyée. Soit c'est la flèche de gauche, et alors les coordonnées de la raquette sont décrémentées de la valeur du pas de mouvement de la raquette VITR, soit c'est la flèche de droite, et ces mêmes coordonnées sont incrémentées de VITR et ce après avoir sauvegardé les anciennes coordonnées dans XRP 0\t arrive ensuite au mouvement de la balle. Le sens de ce mouvement est donné dans la variable ENS ; suivant sa valeur, les coordonnées XB et YB seront incrémentées ou décrémentées de VITB Il faut, après ces opérations, vérifier que la balle n'est pas en butée contre un mur par les tests de bornes de ses coordonnées et vérifier qu'elle n'est pas contre la raquette. Dans chacun de ces cas, elle rebondit avec un angle de réfection égal à l'angle d'incidence. Le test du choc sur la raquette se fait par l'appel au sous-programme, test qui retourne la couleur du point de coordonnées contenues dans les paires de registres DE et HL. Les étiquettes Mi correspondent aux tests de chacun des côtés avec pour chaque côté deux angles d'arrivée possibles. Le bloc de programme "mouvement" se termine par le tracé de la balle après l'avoir effacée de sa position précédente. A l'étiquette LANCE2 se trouvent les lignes de programme nécessaires à l'effacement de la balle lorsqu'elle sort à côté de la raquette.

Ce programme se termine par la réinitialisation du clavier et le retour au Basic. Nous vous souhaitons de passer un agréable moment avec ce jeu, mais il a surtout été écrit dans le but d'être aisément modifiable afin de permettre à chacun de s'initier au langage assembleur. Il peut être transformé en casse-briques, la balle et la raquette peuvent être dessinées différemment. De même, l'emplacement de l'affichage de la raquette pourra être modifié dans le programme, ce qui aura pour action de ralentir ou d'accélérer le jeu. Bon courage !

( La disquette illustrant cet article n'est pas encore numérisée : Deviens riche et célébre en participant TOI aussi au site et complete cette article !! )

Denis BOURQUIN, CPC n°14

★ ANNÉES: 1985
★ AUTEUR: Denis BOURQUIN

★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser...

Lien(s):
» Coding » Initiation a CP/M (18/xx) (CPC Revue n°25)
» Coding » Initiation a CP/M (07/xx) (CPC Revue n°13)
» Coding » Initiation SDCC and CPC by Hans Hansen
» Coding » AMSLIVE n°01 - Init
» Coding » Initiation a CP/M (19/xx) (CPC Revue n°27)
» Coding » Initiation a CP/M (02/xx) (CPC Revue n°8)
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/c
Page créée en 288 millisecondes et consultée 2672 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.