CODINGCHRONIQUE Jean-Pierre Richard pour l'Ordinateur Individuel ★ LANGAGE MACHINE ET ASSEMBLEUR : LES REGISTRES DU Z 80 ★

L'Ordinateur individuel n°19 - Langage Machine et Assembleur : Les Registres du Z80
Le langage d'assemblage et par conséquent le langage machine dépend du «composant » microprocesseur et des fabricants d'ordinateurs individuels ; le programme assembleur peut légèrement différer (ponctuation, édition...) entre deux ordinateurs ayant le même composant de base. La carte mémoire (adresses réservées, adresses disponibles) est différente d'un matériel à un autre ; un programme devra y être adapté avant l'assemblage.

Le langage d'assemblage est différent d'un langage évolué. La connaissance générale des éléments et de la structure interne de l'ordinateur (ou hardware, mot anglais ne possédant pas d'équivalent dans la langue française) est nécessaire pour une programmation efficace.

Chaque microprocesseur a son propre langage d'assemblage mis à part quelques équivalences exceptionnelles. Les structures internes étant très différentes entre microprocesseurs il ne peut en être autrement. A titre d'exemple, le 6800 (Motorola) a deux accumulateurs et peu de registres internes, le Z80 (Zilog) a beaucoup de registres internes mais un seul accumulateur ; il existe également des microprocesseurs à 4, 8, 16 bits...

Devant cette diversité, nous allons nous intéresser au microprocesseur Z 80 de Zilog.

Ce microprocesseur, nec plus ultra des microprocesseurs huit bits est un prolongement du microprocesseur 8080 de Intel. Bien que plus complet que ce dernier sur le plan des instructions et également plus pratique par sa formule en un boitier, le Z 80 a gardé une compatibilité avec le 8080. Il existe une table d'équivalence entre les instructions 8080 et Z 80 (ex. : MOV R1, R2 = LD R1, R2). On dispose ainsi delà «programmathèque » du 8080, très importante étant donné que ce microprocesseur a été un des plus vendus.


Structure interne du Z80 (ci-dessus) et architecture d'un ordinateur qui utilise ce Z80

Les exemples de programmes sont donnés assemblés. Les sceptiques du langage machine assembleur, ne voulant pas «investir» dans un programme assembleur, peuvent introduire les codes machines à l'aide d'un moniteur (TBUG, NAS-BUG...) ou des PEEK et POKE en BASIC.

Il importe de faire tout d'abord un rapide rappel de la structure interne du Z80 et de son emplacement dans l'architecture d'un ordinateur (figure 1 ).

Les registres huits bits B, C, D, E, H, L sont apairables en registres pairs de 1 6 bits BC, DE, HL. Les registres pairs AF et A'F' sont utilisés dans certaines opérations (piles).

La structure d'un langage d'assemblage se décompose en cinq parties distinctes :

  • transfert de données ;
  • opérations arithmétiques et de comparaisons ;
  • opérations logiques, manipulations de bits ;
  • tableaux et chaînes ;
  • entrées et sorties.

Face à cet univers nous pouvons maintenant étudier les instructions de transfert de données.

Elles se présenteront toujours sous ce même format : LD destination, origine.

LD : LOAD (charger en français) destination: registre, adresse, index, label.

Origine : registre, adresse, index, label, donnée.

Nous pouvons donc voir comment effectuer un transfert de données en huit bits avec l'exemple 1.


Exemple 1


Exemple 2


Exemple 3

Tout ce qui est après un point virgule (;) est considéré comme étant «zone commentaires»; c'est le REM du BASIC. Les instructions ORG et END sont des directives d'assemblage. Ces instructions font partie des pseudo-instructions. Nous y reviendrons.

ORG (ORiGine) a défini la première adresse mémoire du premier code machine du programme ;

END indique la fin du programme. Ces deux instructions n'ont pas de code machine mais elles sont nécessaires (et obligatoires!) pour «placer» le programme dans la carte mémoire. Les valeurs des adresses mémoires sont donc à adapter à votre microprocesseur.

Ligne 140 : elle met la donnée 20 hexadécimale dans le registre B. C'est un transfert de type LD registre, donnée.

Le code machine obtenu, 0620, se décompose ainsi : 06 est le code spécifique de l'instruction : LD B, donnée. 20 est la valeur de cette donnée. A la ligne LD B,10Hcorres-pondra le code 0610.

Si la donnée est décimale, le programme assembleur la convertira en hexadécimale (ex: LD B,16 donne 0610).

Ligne 150: la valeur du registre B est copiée dans l'accumulateur A. Le registre B contient encore la valeur 20H. Un transfert d'origine (registre, adresse, index, label) vers la destination (registre, adresse, index, label) ne modifie jamais la valeur de l'origine.

Ligne 160 : la valeur de A est copiée à l'adresse mémoire contenue dans le registre pair HL. C'est un autre principe de base que nous rencontrons.

  • HL est un registre pair qui contient dans notre exemple la valeur 109H.
  • (HL) est une adresse pointée par le registre pair par HL mis entre parenthèses. La valeur de cette adresse est la valeur contenue dans HL.

Ligne 170: la valeur contenue dans l'emplacement mémoire pointé par HL est copiée dans le registre E.

Ligne 190. la valeur contenue dans l'accumulateur est copiée à l'adresse mémoire 0108H. HL est utilisé comme pointeur d'adresse car son jeu d'instructions est très complet : nous le verrons au fur et à mesure.


Exemple 4


Exemple 5


Exemple 6


Exemple 7


Exemple 8


Exemple 9


Exemple 10

L'adressage mémoire peut être direct. Les parenthèses permettent de distinguer cette adresse d'une simple valeur (ex : LD (0108H),A).
Attention ! Dans le cas de transfert de données huit bits, seul l'accumulateur peut être adressé directement par mémoire.

  • LDA A, (n+ n—) ; code machine : 3A n— n+
  • LD (n+ n—), A ; code machine : 32 n— n+

où n+ est l'octet haut, n— l'octet bas.

L'adresse n+ n—, 0108H dans l'exemple, est composée de deux octets (le bus d'adresse du Z 80 est un bus 16 bits). L'octet 08 est appelé octet bas, c'est l'octet le moins significatif. L'octet 01 est appelé octet haut, c'est l'octet le plus significatif.

En code machine, l'octet bas est toujours placé avant l'octet haut : ainsi LD (108H),A se traduit en code machine par 32 08 01.

Cet exemple contient les transferts de données huit bits (sauf adresse indexée que nous verrons dans l'exemple 5). Ne cherchez pas de signification à ce programme ! Il peut à la rigueur faire partie de l'initialisation de registre dans un programme plus long, mais ce n'est pas le plus important.

Etes-vous prêts pour un Transfert de données en 1 6 bits ? Allons-y avec l'exemple 2.

Ce programme initialise les registres B et C avec les valeurs 05H et 02H. Le registre BC contiendra donc la valeur 0502H.

Le Z 80 nous permet de charger directement une valeur 16 bits dans un registre pair.

Dans Y exemple 3, cette instruction distribue automatiquement les deux octets à deux adresses consécutives.

L'octet bas est placé avant l'octet haut comme on peut le voir dans l'exemple 4. Nous pouvons maintenant avec l'exemple 5 effectuer des transferts de données 8 et 16 bits.

Ligne 130: le registre pair HL est chargé de la valeur 4D00H.

Notez bien la distribution de l'octet haut et de l'octet bas de la valeur 4D00H dans le code machine. Ligne 140 : nous avons déjà eu cette forme d'adressage dans l'exemple 1. Une valeur ou un registre pair mis entre parenthèses pointe une adresse mémoire. Ici le registre HL mis entre parenthèses pointe l'adresse 4D00H.

A la ligne 190 nous préciserons quelques restrictions d'utilisation. Ligne 150: la valeur contenue dans HL, deux octets, est copiée à l'adresse pointée par la valeur 4D02H (mise entre parenthèses) pour l'octet haut ; l'octet bas sera copié à l'a-
dresse 4D03H (incrémentation automatique du pointage).

Ligne 160: IX et IY sont des registres d'index (1 6 bits).

Ligne 170: utilisation d'un registre d'index.

L'ensemble (IX+ d) ou (IY + d) indexe une adresse. La valeur de cette adresse est la somme de la valeur contenue dans le registre d'index et du déplacement d. d est représenté en complément à deux : ainsi pour un déplacement de — 1 ,d sera égal à FFH (à suivre...).

Ligne 190: la valeur de l'accumulation est copiée dans l'adresse pointée par BC.

Attention ! Mis à part les registres IX, IY et SP, seul le registre pair HL adresse,ou est adressable par, tous les registres du Z 80.

  • LD B,(HL) OK
  • LD B,(DE) faux !

C'est ce jeu d'instructions supplémentaires qui nous fera choisir le registre pair HL comme conteneur d'adresse dans nos programmes.

Cet exemple nous a permis de programmer un échantillonnage de transferts de données 1 6 bits et 8 bits. Le registre SP sera traité quand nous aborderons les piles.

Intéressons-nous tout d'abord à l'utilisation des labels et des pseudoinstructions.

Maintenant que nous savons manipuler les données dans les registres et les mémoires, voyons une application pratique et simple qui va nous mener très loin, vous allez voir...

Dans l'exemple 6 le premier pas de programme assigne au label ECRAN la valeur 3C00H. L'instruction EQU qui n'a pas de code opératoire est appelée pseudo-instruction. L'assembleur reconnait cette instruction et l'exécute.

Ligne 140: l'adresse du début de l'écran vidéo est copié dans le registre HL par l'intermédiaire du label. C'est maintenant à vous, lecteurs, d'adapter votre programme à votre ordinateur (si ce n'est pas un TRS 80).

Recherchez sur la carte mémoire l'adresse de la mémoire vidéo et remplacer 3C00H par cette valeur. Ligne 150: le code ASCII du caractère entre guillemets est copié dans l'accumulateur : * a pour code ASCII 2A. Cette conversion automatique va nous économiser un temps précieux !

Il existe d'autres pseudo-instructions dont les fonctions sont de définir un ou des octets, un caractère ASCII, un mot ou une chaîne alphanumérique. Elles permettent également de réserver une ou des adresses et d'assigner une valeur à un label ou un label à une adresse. Ce sont les pseudo-instructions suivantes :

  • DEFB (DEFine Byte) assigne un octet à une adresse mémoire. Cet octet est une valeur hexadécimale, une valeur décimale ou un caractère ASCII (exmple 7).
  • DEFW (DEFine Word) a la même fonction que la pseudo-instruction DEFB mais pour deux octets (exemple 8). DEFFH est la représentation en complément à deux de — 34.
  • DEFM (DEFine Message) traduit une chaîne alphanumérique en code ASCII (bien pratique !) (exemple 9).
  • DEFS (DEFine Space) réserve un espace mémoire d'un nombre d'octets égal à n (stockage de données, tableau) (exemple 10).
  • DEFL est une instruction semblable à EQU. Elle permet de pointer une adresse mémoire à l'aide d'un label. DEFL se différencie de EQU par son label qui peut être utilisé plusieurs fois dans le même programme (exemple 11 ).

NB : il est possible de faire des opérations simples sur les labels. Ex : ECRAN + 40H est la ligne suivante.


Exemple 11


Exemple 12


Exemple 13


Exemple 14

L'exemple 12 nous montre une application des pseudo-instructions.

L'exécution de ce programme fait apparaître deux astérisques sur l'écran vidéo. Il existe un moyen plus performant d'afficher une suite de caractères : il suffit de réaliser des sauts conditionnels et inconditionnels comme dans l'exemple 13.

La ligne 170 incrémente le registre pair HL, HLpointe la position suivante de la mémoire vidéo et l'instruction JP BOUCLE branche inconditionnellement le programme à l'adresse du label BOUCLE. L'écran n'ayant que 1 024 adresses, le programme va « se planter » à la 1024e fois. Il faut maîtriser cette boucle par un branchement conditionnel.

Complétons l'exemple n° 13 avec les lignes qui apparaissent dans l'exemple 14 (nous y reviendrons). Ce branchement conditionnel sert de compteur au programme d'affichage d'astérisques et seule la première ligne sera adressée.

Ligne 165: une ligne de l'écran vidéo ayant 64 adresses, B sera donc chargé de la valeur 64 (40H). Ligne 185: l'instruction DEC décroit la valeur du registre désigné, en l'occurrence le registre N.

Ligne 190 : elle teste l'indicateur Z et branche le programme à l'adresse du label BOUCLE si la valeur n'est pas nulle.

Il apparaît maintenant opportun de faire quelques rappels sur le registre indicateur d'état (ci-des-sous).

Le registre indicateur d'état
SZXHXPNC
76543210

Les bits 3 et 5 ne sont pas utilisés Les bits 0,2, 6 et 7 sont utilisés dans les branchements conditionnels du type JP et CALL.

Les bits 0 et 6 sont utilisés dans les branchements conditionnels du type JR.

  • Bit 0 :l'indicateurCindiques'ily a une retenue sur le bit 7 lors d'une opération arithmétique ou logique. Dans un octet le bit 7 est le Bit le Plus Significatif (BPS) (en anglais MSB : Most Significant Bit). Ce bit donne le signe de la valeur dans l'octet en représentation complément à deux.

    — Si le bit 7 est 0 la valeur est positive.
    — Si le bit 7 est 1 la valeur est négative.

    JP NC, nn : branche le programme à l'adresse nn, s'il n'y a pas eu de retenue lors d'une opération arithmétique ou logique. JP C, nn : branche le programme à l'adresse nn s'il y a eu une retenue lors d'une opération arithmétique ou logique.

  • Bit 2 : l'indicateur P a deux fonctions :

    a) la parité : si le nombre de bits à l'état 1 dans un octet est pair, Pest égal à un (parité paire). Si le nombre de bits à l'état 1 dans un octet est impair, P est égal à zéro (parité impaire).
    b) le dépassement : l'indicateur P indique s'il y a dépassement dans le résultat d'une opération arithmétique ou logique. Cette fonction est difficile à différencier de l'indicateur C. Nous verrons, lors de l'étude de la représentation en complément à deux, qu'il peut y avoir une retenue sans dépassement. (C = 1, P = 0).

    JP PO, nn : branche le programme à l'adresse nn si la parité est impaire ou s'il n'y a pas eu de dépassement.
    JP PE, nn : branche le programme à l'adresse nn si la parité est paire ou s'il y a eu dépassement.

  • Bit 6 : l'indicateur de zéro (Z) a pour valeur 1 si le résultat de l'opération arithmétique ou logique est nul. Il sera au niveau logique 0 si le résultat est différent de zéro ou 1 si le résultat est nul.

    JP NZ nn : branche le programme à l'adresse nn si le résultat de l'opération est différent de zéro.
    JP Z, nn : branche le programme à l'adresse nn si le résultat de l'opération est nul.

    ATTENTION : c'est le résultat et non le bit 6 qui est contrôlé !

  • Bit 7 : l'indicateur S contient le BPS du résultat en complément à deux. Si le résultat est positif (+) ou négatif (—), le bit 7 sera respectivement 1 ou 0. Cette fonction permet de contrôler le signe d'un octet. JP P, nn : branche le programme à l'adresse nn si le résultat de l'opération arithmétique ou logique est Positif.

    JP M, nn : branche le programme à l'adresse nn si le résultat est négatif (Minus).

    Ces conditions de branchement s'appliquent de la même façon pour JP, JR (0 et 6 seulement) et CALL. Nous rencontrerons fréquemment l'utilisation de ces instructions dans les programmes suivants.

L'organigramme 1 correspond à l'exemple 14.

Si vous trouvez l'affichage de l'astérisque trop rapide ou si vous désirez afficher l'astérisque toutes les secondes, par exemple, il faut imbriquer une boucle « à vide »dans la 1re boucle (exemple 15). L'organigramme 1 devient l'organigramme 2.

L'instruction DJNZ, nn permet de décrémenter la valeur du registre B et d'effectuer un branchement vers l'adresse ou le label tant que cette valeur ne sera pas nulle. Cette instruction ne s'applique qu'au registre B L'organigramme du programme 13 sera ainsi modifié pour donner l'organigramme 3.


Organigramme 1


Organigramme 2

Si la valeur maximum de FFH (256) ne donne pas un temps suffisamment long, nous pouvons utiliser un registre pair. La valeur du registre pair DE est contrôlée par une addition logique entre l'accumulateur, préalablement chargé de la valeur D, et le registre E (exemple 16).

Le résultat qui se trouve dans l'accumulateur met à 1 l'indicateur d'état Z s'il est nul. L'instruction JR, n est un branchement relatif inconditionnel ou conditionnel.

  • inconditionnel JR, d L'instruction branche inconditionnellement le programme à l'adresse contenue dans le pointeur de programme PC additionnée de la valeur du déplacement d. Ce branchement peut s'effectuer à une adresse en amont ou en aval de l'emplacement actuel, dans une limite de + 127 ou — 128 octets.

  • conditionnel JR CC, d

L'instruction branche le programme, si la condition CC est remplie, à l'adresse contenue dans le pointeur de programme PC additionnée de la valeur du déplacement d. Ce branchement peut s'effectuer à une adresse en amont ou en aval de l'emplacement actuel (limite + 1 27, — 128 octets), d est soit une valeur en représentation complément à deux, soit un label.

CC peut être Z, NZ, C, NC.

L'instruction JR donne un code machine indépendant de l'emplacement actuel du programme dans la mémoire. Cette propriété rend le programme relogeable dans la carte mémoire et détermine souvent le choix de cette instruction (exemples 17 et 18).

Vous avez en main plus d'une centaine d'opérations d'assemblage possibles, alors avant d'en apprendre d'autres, entraînez-vous ! Modifiez les exemples, créez d'autres programmes (caractèrequi clignote, qui se déplace...) et n'oubliez surtout pas cette morale : MILLE FOIS sur le clavier remettez votre programme...


Organigramme 3


Exemple 15


Exemple 16


Exemple 17


Exemple 18

Jean-Pierre Richard, L'Ordinateur individuel n°19

★ REVUE: L'Ordinateur Individuel
★ ANNÉE: ???
★ AUTEUR: Jean-Pierre RICHARD

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 332 millisecondes et consultée 375 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.