CODINGCLASSEURS WEKA ★ Comment exploiter toutes les ressources et augmenter les performances de votre AMSTRAD CPC ★

4/2.5.1 - III. Un programme machine plus utileCoding Classeurs Weka
4/2 - Assembleur Z80 : Définitions et rappels de base

4/2.5 - Cours de programmation

4/2.5.1 Initiation au langage machine

III. Un programme machine plus utile

Pratique pour faire comprendre un certain nombre de notions importantes, ce premier programme n'a certes pas une grande utilité pratique !

Attaquons-nous donc maintenant à la résolution d'un problème précis, difficile à traiter en Basic. Vous connaissez certainement le code ASCII, qui affecte un octet déterminé à chaque caractère susceptible d'être affiché par l'Amstrad : en décimal, le « A » est représenté par l'octet 65, et le « Z » par 90, par exemple. (Voir les fonctions BASIC, ASC et CHR$.)

Le tableau suivant rappelle qu'un octet peut être représenté sous la forme de huit « bits » pouvant être soit à 1 soit à 0, et dont chacun possède un « poids » bien précis : celui de droite, le moins « significatif », vaut 1 lorsqu'il est à 1 et évidemment 0 lorsqu'il est à 0.

27 26 25 24 23 2² 2¹ 20
128 64 32 16 8 4 2 1
A0 1 0 0 0 0 0 1 65
Z0 1 0 1 1 0 1 0 90

Celui de gauche, le plus significatif, vaut 128 lorsqu'il est à 1 et toujours 0 lorsqu'il est à 0. De droite à gauche, les huit bits de l'octet valent respectivement 1, 2, 4, 8, 16, 32, 64 et 128, soit un total maximal de 255 s'ils sont tous à 1.

Or, 127 combinaisons suffisent largement pour coder tous les caractères de l'alphabet informatique normalisé : lettres majuscules et minuscules, chiffres et signes divers. Sept bits suffisent donc, et si l'on persiste à travailler avec des octets de huit bits (le matériel est fait pour cela), le bit de poids fort (128) reste normalement à 0.

Il a été imaginé de se servir de ce huitième bit pour contrôler les altérations pouvant survenir dans les transmissions de données : ce bit, appelé bit de parité, est mis à 1 ou à 0 selon le nombre de bits qui sont eux-mêmes à 1 dans le « septet » représentant le caractère. Le Minitel, par exemple, travaille en parité paire : le huitième bit est positionné de façon à ce que le nombre total de bits à 1 dans l'octet soit pair. A l'arrivée, on compte les bits à 1 et si le nombre trouvé est impair, on déduit qu'il y a eu erreur dans la transmission !

Bien évidemment, cela n'a rien à voir avec la « parité » de la valeur décimale de l'octet, au sens arithmétique du terme. Le tableau suivant montre le résultat de ce traitement sur les octets valant, en décimal, de 0 à 8. Cette valeur d'origine se trouve augmentée de 128 lorsque le bit de parité doit être mis à 1. En Basic, l'adjonction du bit de parité serait une opération lourde et lente. En langage machine, une routine de douze octets suffit, soit l'équivalent d'une seule très courte ligne de Basic.

Bit de parité27 26 25 24 2³ 2² 2¹ 20
Avant128 64 32 16 8 4 2 1 Après
00 0 0 0 0 0 0 0 0
11 0 0 0 0 0 0 1 129
21 0 0 0 0 0 1 0 130
30 0 0 0 0 0 1 1 3
41 0 0 0 0 1 0 0 132
50 0 0 0 0 1 0 1 5
60 0 0 0 0 1 1 0 6
71 0 0 0 0 1 1 1 135
80 0 0 0 1 0 0 1 9
911 0 0 0 1 0 0 0 136
etc.

Principe de codage en parité paire : le huitième bit de l'octet sert de bit de parité

Etudions donc en détail ce programme sous une forme qui vous sera bientôt familière :

40000 LD A,0 62 0
40002 AND A 167
40003 JP PE 40008 234 72 156
40006 SET 7,A 203 255
40008 LD 40001,A 50 65 156
40011 RET 201

La colonne de gauche indique l'adresse mémoire à laquelle est implanté le premier octet (ou l'octet unique) de chaque instruction : la première instruction comportant deux octets, on comprend pourquoi on passe de 40000 à 40002 !

Par contre, la seconde instruction ne possédant qu'un octet, on passe de 40002 à 40003.

Insistons bien sur le fait qu'une routine machine est en général écrite pour être implantée à partir d'une adresse mémoire bien déterminée : la déplacer équivaudrait à renuméroter les lignes d'un programme Basic sans corriger les GOTO et les GOSUB !

Certaines techniques de programmation permettent d'écrire des routines « relogeables », pouvant fonctionner n'importe où en mémoire, mais on ne peut pas toujours les employer.

La seconde colonne donne le mnémonique de l'instruction, c'est-à-dire la description très abrégée de ce qu'elle fait : c'est sous cette forme qu'on programme en « assembleur ».

Pour programmer « à la main » en langage machine, il faut faire le travail du logiciel assembleur à l'aide d'un crayon et de papier : aller chercher dans les recueils d'instructions les codes opératoires (octets) correspondant à chaque mnémonique, et calculer à l'aide de tables ou à la machine les octets servant à « pointer » des adresses mémoire. C'est long et fastidieux, mais extrêmement formateur : pour bien utiliser un assembleur, il faut savoir comment il fonctionne !

La première instruction du programme charge la valeur 0 dans le « registre » A du Z 80. Ce microprocesseur possède plusieurs de ces registres, 22 pour être précis. On trouvera leur description précise en partie 4, chapitre 2.2, mais sachez pour le moment que le plus utilisé est A, nommé « accumulateur ».

En fait, la valeur 0 sera remplacée juste avant l'exécution par l'octet à traiter : il suffira pour cela de faire, en Basic, POKE 40001, (octet) juste avant le CALL 40000.

Vous pouvez donc mettre n'importe quelle valeur inférieure à 256 à la place de 0, mais ne touchez pas à 62 qui est le code opératoire de l'instruction LD, A,N (LOAD A with N) qui charge A avec N.

L'instruction suivante, AND A, est utilisée de façon particulière : normalement, AND effectue un ET logique bit à bit entre l'octet contenu dans A, et celui contenu dans le registre spécifié. Ici, le ET est effectué entre le contenu de A et le contenu de A ! Bien évidemment, le contenu de A n'est pas modifié, mais l'exécution de l'instruction AND positionne le « drapeau » de parité du Z 80 : cet indicateur se « souviendra » donc de la parité du contenu de A, c'est-à-dire s'il contient un nombre pair ou impair de bits.

L'instruction suivante fonctionne comme un IF-THEN en Basic : JP PE 40008 (jump to 40008 if parity even) déclenche un saut à l'instruction logée à l'adresse 40008 si et seulement si le drapeau de parité est positionné sur « pair ». Dans le cas contraire, c'est l'instruction suivante qui est exécutée, celle qui est logée en 40006.

234 est le code opératoire de JP PE NN, tandis que 72 et 156 représentent l'adresse 40008 (72 + (256 x 156)) : l'octet le moins significatif de l'adresse est toujours placé en premier, suivi de l'octet le plus significatif, dont le « poids » est 256.

Si la parité est impaire (nombre impair de bits), l'instruction SET 7,A est exécutée : elle force à 1 le bit de poids fort (N° 7) du registre A, ce qui rend pair le nombre total de bits.

Si la parité était déjà paire, c'est l'instruction LD 40001 ,A qui est exécutée : le contenu de A est chargé dans l'adresse mémoire 40001 (65 + (256 x 156)) où le Basic pourra venir le chercher par un PEEK 40001.

Encore faut-il pour cela revenir en Basic, ce qui est déclenché par l'instruction RET, équivalente au RETURN du Basic. Le programme suivant se charge à la fois de l'implantation en mémoire de cette routine (lignes 10 à 60), et de son exploitation pratique dignes 100 à 140).

10 MEMORY 39999
20 DATA 62,0,167,234,72,156,203,255,50,65, 156,201
30 FOR f=40000 TO 40011
40 READ c
50 POKE f, c
60 NEXT f
30 REM (c)1988 Patrick GUEULLE
100 FOR f=0 TO 127
110 POKE 40001,f
120 CALL 40000
130 PRINT f ; " ". PEEK(40001)
140 NEXT f

Programme Basic d'implantation et de lancement

Dans un premier temps, de la place mémoire est protégée, bien plus qu'il n'en faut d'ailleurs, mais au diable l'avarice !

Les douze octets, rangés dans une ligne DATA, sont alors implantés en mémoire par une suite de POKE déclenchés par une boucle FOR-NEXT opérant directement sur les adresses mémoire 40000 à 40011.

La routine peut maintenant être appelée à volonté par un simple CALL 40000, à charge pour l'utilisateur de placer d'abord l'octet à traiter en 40001 par un POKE.

C'est ce que fait la seconde partie du programme, qui affiche à l'écran les octets 0 à 127 enrichis d'un bit de parité paire.

Comparez donc le début de cette liste avec la colonne de droite du tableau page 6 et, si le cœur vous en dit, essayez de faire aussi bien et aussi rapide sous Basic : bonne chance !

★ NOTE: 9e Complément

Page précédente : 4/2.5.1 - II. Votre première routine machine
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.732-desktop/c
Page créée en 167 millisecondes et consultée 822 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.