Par quel moyen peut-on faire naître chez vous une vocation pour la micro-machinaction ? Les deux articles précédents vous ont livré sous forme de « concentré écrit » une introduction à la programmation en assembleur. Avec un ordinateur équipé d'un langage évolué, il suffit de franchir l'étape d'initiation aux instructions avec quelques exemples à l'appui pour se lancer dans la programmation (4 à 8 heures pour le BASIC). Au contraire, le langage machine et son traducteur «assembleur» exigent du programmeur un effort plus important pour devenir opérationel : essentiellement se mettre à l'échelle du microprocesseur, connaître sa capacité et apprendre son vocabulaire-clé.
Figure 1 >> Mais peut-être faut-il comparer ce qui est comparable... Si vous ne voyez pas ce que je veux dire, voici un même programme en langage machine et en BASIC dont l'exécution vous fera rejoindre, je l'espère, le rang des « mordus » de la micro-machinaction. L'organigramme de ce programme est présenté par la figure 1. Le programme machine (figure 2) est uniquement composé d'instructions vues dans l'article 2. La suite logique des opérations de ce programme ne doit plus avoir de secrets pour vous. La limitation à ces quelques instructions «alourdit» sérieusement le programme : nous verrons comment le simplifier par la suite. La ligne 130 contient l'adresse dans la mémoire de la zone de début de l'écran pour le TRS-80. Si vous ne possédez pas ce système, adaptez cette adresse suivant la carte mémoire de votre O.I. La figure 3 nous donne la liste du programme en langage BASIC et la figure 4 représente le programme BASIC qui charge en mémoire le programme en langage machine puis qui l'exécute. Les lignes 1040 et 1050 initialisent le pointeur désignant l'adresse de démarrage du sous-programme en langage machine pour le TRS-80. (Il faut l'adapter à votre système si ce n'est pas un TRS-80). Rentrez les programmes de la figure 2 et de la figure 3 dans votre machine et faites les tourner, puis chronométrez, vous serez alors convaincus !  Figure 2
 Figure 3
 Figure 4
Les instructions de transfert de blocs de données Nous avons vu dans les articles précédents les instructions LD, JP, JR et les pseudo-instructions DEFB, DEFW, DEFS, DEFL, EQU, ORG et END. Nous allons maintenant étudier les instructions de transfert de blocs de données. Ces instructions de transfert font du Z-80 un microprocesseur très puissant ; elles permettent de déplacer un bloc de données d'un emplacement mémoire vers un autre. Instructions LDI (LoaD Incrément: charger en incrémentant) et LDIR (LoaD Incrément Repeat: charger en incrémentant de façon répétée). Les registres paires HL, DE, BC doivent être initialisés de la manière suivante : - HL : adresse du premier octet « origine »
- DE : adresse du premier octet « destination »
- BC : nombre d'octets à déplacer.
L'instruction LDI déplace l'octet contenu à l'adresse pointée par DE ; HL et DE sont incrémentés d'une unité, BC est décrémenté d'une unité. L'instruction LDIR fonctionne comme LDI mais le transfert d'octets se fera tant que BC n'est pas devenu égal à 0. Instructions LDD (LoaD Decre-ment : charger en décrémentant) et LDDR (LoaD Decrement Repeat : charger en décrémentant de façon répétée). L'initialisation des registres paires HC, DE, BC est la suivante : - HL: adresse du dernier octet «origine »
- DE : adresse du dernier octet « destination »
- BC : nombre d'octets à transférer.
L'instruction LDD déplace l'octet contenu à l'adresse pointée par HL vers l'adresse pointée par DE : HL, DE et BC sont décrémentés d'une unité. L'instruction LDDR fonctionne comme LDD mais le transfert d'octets se fera tant que BC n'est pas devenu égal à 0.  Figure 5
 Figure 6
L'exécution du programme, dont la liste est donnée à la figure 5, affiche le mot « micromachinaction » sur l'écran. La ligne 120 LONTEX EQU S-TEXTE est une opération d'assemblage définie par le symbole $ - qui permet d'assigner au label LONTEX le nombre de caractères ASCII de la chaîne alphanumérique «TEXTE» Ce programme est simple ; assimilez-le bien avant de continuer. Si vous ne comprenez pas la signification des contenus des différentes colonnes, reportez-vous au premier article de la série, paru dans L'Ordinateur Individuel n° 18 pp. 91-94. Ne jamais enlever l'assiette du bas de la pile Voyons maintenant les opérations sur pile LIFO. Le mot «pile» (stack) définit une zone mémoire de stockage de données dont la structure est analogue à une pile d'assiettes (les assiettes étant les données). Si nous rangeons une assiette, nous la posons (instruction PUSH) sur le sommet de la pile ; si nous prenons une assiette (instruction POP) dans cette pile, c'est évidemment celle du dessus, soit la dernière posée, que nous choisirons. En anglais, ces opérations s'expriment par Last In First Out (LIFQ), c'est-à-dire dernier entré, premier sorti. Le repérage de chaque donnée, ou assiette, est assuré par le registre 16 bits pointeur de pile: SP (Stack Pointer). Le contenu de SP est une adresse qui désigne, comme un doigt, une assiette quelconque de la pile, en général celle du dessus. L'instruction POP RR recopie les contenus des deux octets du sommet de la pile dans le registre paire RR; l'instruction PUSH RR pousse les deux octets contenus dans le registre paire RR au sommet de la pile ; le registre paire RR peut être AF, BC, DE, HL, IX ou IY. L'instruction PUSH RR a pour effet de décrémenter d'une valeur égale à deux le registre SP : l'octet le plus significatif du registre paire RR sera chargé à l'emplacement SP-1 ; l'octet le moins significatif sera chargé à l'emplacement SP-2. Chaque fois qu'on ajoute donc une assiette sur la pile par PUSH, le pointeur est automatiquement modifié afin de désigner ce qui est devenu le nouveau sommet de la pile. L'instruction POP RR engendre l'opération inverse : en retirant les deux octets contenus au sommet de la pile, le pointeur redescend de deux crans. Ces opérations sur pile et pointeur de pile sont utilisées lors des appels de sous-programme (pour stocker l'adresse de retour), de sauvegarde de registre ou d'échange de valeur entre registres. Reprenons l'exemple 5 et supposons que celui-ci s'insère dans un programme beaucoup plus important. Les trois registres paires BC, DE, HL seront probablement déjà utilisés et contiendront des valeurs à ne pas perdre. Le programme modifié se présentera alors de la façon suivante : LD SP, PILE PUSH HL PUSH DE PUSH BC POP BC POP DE POP HLAprès avoir initialisé le pointeur de pile SP(pour indiquer où est la table sur laquelle on va commencer à poser les assiettes), les registres contenant des valeurs à sauvegarder sont empilés. Alors seulement on peut travailler avec ces registres. Lorsqu'on en a terminé, on restaure les registres. La machine est à nouveau dans l'état qu elle avait avant l'exécution du programme exemple 5.Le label PILE contient une adresse qui pointe une zone mémoire réservée à la pile. Il faut remarquer l'ordre dans lequel HL, DE et BC sont poussés (PUSH) sur la pile et l'ordre dans lequel ces regisLes instructions d'échange permettent un stockage temporaire très paires sont chargés (POP) dernier rentré : BC, premier sorti : BC. Voyons maintenant les instructions d'échange EX et EXX. Ces instructions opèrent des échanges réciproques de valeur entre registres paires et registres 16 bits. L'instruction EX(SP), RR échange le contenu du registre paire RR avec les deux octets du sommet de la pile. RR peut être HL, IX ou IY. L'instruction EX DE, HL permute les valeurs des registres paires DE et HL. L'instruction EX AF, A'F' permute les valeurs des registres paires AF et A'F'. L'instruction EXX échange les valeurs des deux jeux de registres (exemple 6). Cette instruction permet un stockage temporaire de la valeur du jeu de registres principal. Abordons maintenant, avec entrain, les instructions d'appel et de retour. La rencontre de l'instruction CALL nn dans un programme provoque un saut (conditionnel ou non) à l'adresse nn(nn peut aussi être un label). La valeur du registre PC (compteur de programme) est automatiquement sauvegardée dans la pile. L'instruction RET de retour (conditionnel ou non) charge (POP) le registre PC des deux octets situés au sommet de la pile ; le programme reprend son cours là où il s'était arrêté. On trouvera dans ces sous-programmes des temporisations, des calculs arithmétiques (multiplication, division...) ou des «repiquages » dans le programme BASIC (gestion du clavier, effacement de l'écran...). Lors de la création d'un programme de travail (calcul, boucle...), une très grande importance sera donnée à ses possibilités de re-logeabilité (JR au lieu de JP... ; voir l'article 2). Il sera ainsi utilisable comme sous-programme dans n'importe quel programme. Comme en BASIC, les sous-programmes peuvent appeler d'autres sous-programmes (figure 7). Les bits 0, 2, 6 et 7 du registre indicateur d'état sont utilisés comme condition de saut pour les instructions CALL et RET.  Figure 7
Utilisez en assembleur aussi les sous-programmes Je vous propose à titre d'exemple et d'entraînement la recherche d'un sous-programme (relogeable avec JR) ralentissant l'exécution du programme de la figure 2. Ce sous-programme devra rendre le déroulement du programme machine aussi lent que celui du programme BASIC. Jusqu'où va le vice... L'instruction RST P provoque une exécution semblable à l'instruction CALL. RST P branche le programme à l'adresse P, tout en sauvegardant le registre PC pour le retour. L'adresse P ne peut prendre que huit valeurs différentes (0000, 0008, 0010, 0018, 0020, 0028 et 0030). Ce mode d'adressage est appelé adressage page zéro. Son code machine est d'un octet, contre trois octets pour CALL ; son exécution est plus rapide mais le sous-programme appelé est constitué de huit octets au maximum. Ces huit octets serviront souvent à logerune instruction de saut conditionnel vers un programme plus important. Cette instruction, qui semble faire double emploi avec CALL est très utile à cause de la faible taille de son code machine. Supposez que le microprocesseur soit interrompu ou arrêté, inerte. Pour le faire rédémarrer, il suffira que se présente à lui un seul octet (le RST) au lieu de trois (le CALL). C'est beaucoup plus facile à réaliser électroniquement. Vous avez fait un grand pas (si ! si I). D'abord parce que vous avez lu cet article jusqu'ici et ensuite parce que l'étude des instructions de transfert est terminée. Expirez - Inspirez. Comme je vous vois en pleine forme, j'aimerai éclaircir un point important du langage machine : le code objet.  Figure 8
 Figure 9
 Figure 10
Toutes les instructions de transfert de données (8 et 16 bits) ont le format suivant : LD destination, origine.Dans le cas où la destination et l'origine sont deux registres 8 bits, le code objet (un seul octet) se présentera selon la figure 8 ; si la destination est un registre et l'origine une valeur, le code objet (deux octets) se présentera selon la figure 9 et si la destination est un registre et l'origine le contenu d'une adresse mémoire, le code objet (trois octets) se présentera comme dans la figure 10.Et ainsi de suite... Certains livres spécialisés dans la programmation du Z-80 donnent une liste complète de ces codes machines — C'est tout bête. Le code objet, c'est la traduction binaire du code machine, un chiffre hexadécimal étant représentable avec quatre chiffres binaires. Les codes machines des instructions de transfert de données 8 et 16 bits, en fonction de l'origine et de la destination, sont récapitulés dans les tableaux de la page 103. 

Ces tables permettent un accès rapide au code machine d'une instruction. Leurs utilisations sont intéressantes lors de la création, la modification ou l'optimisation d'un programme. Le choix de telle ou telle instruction est déterminé par le nombre d'octets de son code machine (occupation de pas mémoire), sa rapidité d'exécution et son environnement (action sur un indicateur d'état pour gérer un saut conditionnel par exemple). Les instructions du langage d'assemblage que vous avez étudié représentent 80% des ordres d'un programme normal ; mais ne poussez pas de Ouf! Ce serait prématuré : nous n'avons envisagé que 50% des difficultés. Il nous reste à étudier les instructions de calcul et de notation. Ce n'est pas un monde... Pour terminer, je vous invite à méditer sur cette pensée d'un grand homme français: «la difficulté attire l'homme de caractère, car c'est en l'étreignant qu'il se réalise lui-même ». Jean-Pierre Richard , L'Ordinateur Individuel n°20 CPCrulez[Content Management System] v8.732-desktop/c Page créée en 275 millisecondes et consultée 196 foisL'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. |
|