CODING ★ AU P'TIT MAL ★

Assembleur ACPC n°43
Si l'assembleur paraît parfois complexe, il n'en est pas moins langage de programmation. Pour en arriver à vos fins, et contrairement au Basic, il faut prendre le temps de penser aux programmes à écrire avant de se jeter sur son clavier. Nous allons donc ce mois-ci vous proposer quelques routines qui, une fois expliquées, vous seront plus claires.

Nous disions donc qu'il fallait penser les routines avant de les écrire. Très bien, pensons. Imaginons un programme chargé de gérer un compteur à l'affichage.

Disons que la valeur passée à ce compteur serait au maximum d'une longueur de quatre caractères. Cela nous donne a priori plusieurs manières de travailler.

Le premier mode serait de simplement gérer la valeur sur un mot de seize bits et de l'afficher en lui faisant subir de multiples soustractions des poids forts des puissances de dix.

En voici l'organigramme approximatif ;

LD HL,VALEUR
LD DE,1000
CALL TRAITE
LD DE,100
CALL TRAITE
LD DE,10
CALL TRAITE
LD A,L
JR AFFICH
TRAITE
XOR A
CPL

SOUSTR
SBC HL,DE
INC A
JR NC,SUBST
ADD HL,DE
AFFICH
OR #30
JP #BB5A

Avec ce type de code, que je trouve personnellement fort joli, il vous est possible de mieux comprendre les problèmes que peut poser la lecture de l'assembleur. On distingue, a première vue, trois CALL internes, mais pas un seul RET. Magique ? No, no ... Bigastuss ! Si vous vous amusiez à tracer le vecteur #BB5A, chargé en ROM d'imprimer le caractère dont le code ASCII est passé par l'accumulateur, vous vous apercevriez qu'il se termine purement et simplement par un RET, ceci pour redonner la main à l'appelant. Nous avons donc un tracé du type :

#BB5A : …


RET

Lorsqu'on appelle cette routine par l'intermédiaire d'un CALL, l'adresse suivant cette instruction est sauvegardée sur la pile, le saut en #BBEA est effectué et lors de la rencontre du RET, nous avons un équivalent d'un JP a l'adresse sauvée sur la pile et donc à l'emplacement mémoire situé juste après l'appelant. En clair, le CALL TRAITE empile l'adresse d'appel et se branche en TRAITE. Le sous-programme s'exécute et rencontre le JP #BB5A. Pour ne pas contredire le maître des lieux, brave 280, il plonge à cette adresse et exécute la routine d'affichage. Tout à coup, il tombe sur le RET. D'un bon réflexe, il dépile l'adresse préalablement déposée sur la pile par le CALL TRAITE et s'en va voir s'il est la-bas (le pire c'est qu'il s'y trouve lorsqu'il y arrive). Simple, non ? Je suis d'accord avec ceux qui pensent que c'est moins lisible que les lignes suivantes :

CALL TRAITE

TRAITE

CALL#BB5A
RET

Cela est exactement du même acabit, saut que deux adresses au lieu d'une sont rencontrées sur la pile et que deux RET sont pareillement rencontrés par le programme. Si vous appelez cette routine trois fois par jour, cela n'est pas bien grave mais si c'est dix fois par seconde qu'elle est appelée, il vaut mieux faire attention aux bits qui traînent. Il en va de la rapidité du programme principal. On peut parfaitement se permettre de perdre du temps dans le corps d'un programme imposant si les routines souvent appelées sont écrites avec soin et précision. Voici maintenant les explications lignes par ligne de ladite routine. LD HL,VALEUR : remplit le registre HL avec la valeur à afficher. Je vous conseille de choisir une valeur entre 0 et 9999, la plus inédite possible et surtout n'importe laquelle de préférence (je vous propose tout de même de prendre 5781, ce qui est le tour détaille de Poum en dixième de millimètres!. PS ; pour le nombre de poils qu'il a dans le dos, le CPC ne possède pas encore de microprocesseur 256 bits :
ENDPS,

LD DE,1000 : nous allons commencer par comparer HL à 1000 ainsi qu'à ses multiples.

CALL TRAITE : appel de la routine de traitement.

LD DE,100 : idem pour cent, pour cent idem.

CALL TRAITE: des vaches.

LD DE,10 : que dire pour dix, idem itou.

CALL TRAITE: des blanches.

LD A,L : Lodaël, petite bourgade du sud de l'Iran où Poum a passé son enfance entre plage, coquillages et mer nacrée (NDPoum : Tout faux Sinoux, c'était le nord). Opération permettant aussi de récupérer dans A les unités restant encore dans le double registre HL. A ce stade, H est forcément neutre, comme au tour précédent mais pour des raisons de compacité, nous avons préféré ne pas le traiter à part. JR

AFFICH : appel direct de la routine d'affichage car aucun traitement n'est utile, sortie théorique du programme car aucun retour n'est plus possible.

TRAITE : label comme elle le mérite.

XOR A : mise à 0 de l'accumulateur,

CPL : mise à -1 de ce même registre par inversion de tous ses bits. Je ne sais pas ce qui est le plus rapide mais j'aime bien utiliser des trucs comme cela de temps en temps. CPL équivaut en fait à un XOR #FF, mais en plus court et avec le XOR A précédent, on arrive à un truc du type LD A,#FF ; mais en plus compliqué et moins lisible, histoire de brouiller les cartes. Je divague ("Vague?").

SOUSTR : ainsi parlait Sarah, label

SBC HL,DE : si se baisser donne des courbatures, SBC permet de soustraire DE de HL. Dans ce cas, deux solutions. Si HL est toujours plus grand que zéro, il y va une fois 1000. Dans le cas contraire, il était trop petit pour jouer avec les grands.

INC A : on incrémente A. Comme il valait -1, son premier passage le force à 0 et les suivants l'i ne ré mentant petit à petit.

JR NC,SUBST : si HL était plus grand que zéro, la boucle est réexécutée. Dans le cas contraire, HL est maintenant négatif, ce qui nous oblige a ne plus le traiter.

ADD HL,DE : comme HL est négatif, il nous faut le rétablir. Nous faisons cela en lui redonnant ce que nous lui avons pris de trop. Notez tout de même que l'accumulateur n'a pas besoin d'être modifié car il avait été préparé préalablement (chargé avec -1 donc possédant un tour de retard).

AFFICH : label, label AFFICH. OR #30 : c'est la forme de conversion la plus simple pour passer d'un chiffre à son code Ascii, seulement si ce premier est inférieur à 10.

JP #BB5A : appel de la ROM avec, en prime, retour au programme appelant, qui peut être un des CALL du programme ou simplement le programme ayant appelé tout ce machin.

LES GRANDS REMEDES

Comme vous l'avez vu, ce genre de programmation est assez tarabiscoté, voire burlesque. Pourquoi s'amuser à imbriquer des programmes qui s'appellent les uns les autres pour finir par la sous-routine qui n'est en fait que partie du programme lui-même ? Pourquoi tant d'allées et venues alors que ce code aurait pu simplement être linéaire, donc plus rapide, donc plus mieux en plus ? Là encore, je ne vous conseille que de bien penser à votre programme. Si des passages ont besoin d'être rapides et que vous ne manquez pas de place, pourquoi ne pas développer ceux-ci et perdre quelques octets au profit de la vitesse ? Prenez votre temps, travaillez sur papier, économisez votre clavier, pensez et votre programme en découlera de lui-même, comme la lave d'un volcan, comme un bouquet d'oiseaux qui s'enfuit au cri de l'arsenal du chasseur. On ne saurait jamais trop vous conseiller de tourner 2 562 145 102 fols votre langue dans votre bouche avant de dire des bêtises. Faites de même en programmation.

LES CURES DE DÉTENTE

Pour que tout cela entre définitivement dans vos jolis cerveaux déjà endoloris pas tant de mots puérils, je vous propose un exercice de style (voilà une phrase habile). Ajoutez à cette routine un petit passage permettant de ne pas imprimer de caractères zéros à gauche du nombre. Débrouillez-vous pour remplacer ceux-ci par des espaces. Puis, si le Cœur vous en dit, remplacez ces espaces par du vide, histoire de formater à gauche la valeur affichée. Il va sans dire que cela ne sera pas sans ajouter quelques lignes de code et quelques variables de travail. Je vous en laisse le soin.

PASSAGE EN PUISSANCE

Nous avons fait un affichage de score au demeurant très propre, mais le type de données de départ nous a un peu trop forcé la main. Sachez que le coding, art de choisir la manière dont seront organisées les données, est primordial dans le déroulement des programmes. Imaginez que nous décidions de stocker notre score en tant que chaîne de caractères. Son traitement en deviendrait du type :

LD HL,FINNB
PRECED
DEC HL
LD A,(HL)
INC A
LD (HL),A
CP #3A
JR NZ,AFFICH
LD (HL),#30
JR PRECED
AFFICH
LD HL,DEBNB
LODCAR
LD A,(HL)
OR A
RET Z
CALL #BB5A
INC HL
JR LODCAR

DEBNB
DEFM 1235
FINNB
DEFB 0

Tracez vous-même cette routine et vous verrez que son fonctionnement en est très simple. On prend les caractères par la fin de la chaîne et on les incrémente. Si le caractère est toujours un chiffre, alors on passe à l'affichage après avoir stocké le résultat. Dans le cas contraire, on met le chiffre actuel à zéro et on passe au précédent. L'avantage de cette routine est qu'elle incrémente automatiquement le score et que pour ajouter toute puissance de 10. il suffit d'y entrer avec HL pointant dans la chaîne (LD HL,FINNB-1 fait prendre 10 à la valeur, LD HL,FINNB-2 lui fait ajouter 100,,,),

ET PI
TA LEUGUE

Comme vous le voyez, avec deux formes de pensée différentes, nous avons fait deux programmes identiques. Non pas que l'un ou l'autre soit mieux ou non, mais tout n'est que question de style, La même personne les a écrites dans des moments d'inspiration différents. A vous de concrétiser vos pensées.

Sined , ACPC n°43, avr/mai 92

Page précédente : Bidouilles ACPC n°42 - La decompression

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

Lien(s):
» Coding » Bidouilles ACPC n°48 - Les vecteurs system (6/6)
» Coding » Bidouilles ACPC n°32
» Coding » Assembleur ACPC n°31 - La femme au scroll infame
» Coding » Bidouilles ACPC n°29 - Le secret des disquettes
» Coding » Bidouilles ACPC n°37 - FDC en mode direct
» Coding » Assembleur ACPC n°16: Organisation des pixels à l'écran
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 003 millisecondes et consultée 1595 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.