Triceraprog
La programmation depuis le Crétacé

Z80 et VG5000µ ()

Lors des articles précédents sur l'affichage, un résultat était net : c'est lent ! Extrêmement lent. Les magazines ou de livres consacrés à la programmation des machines personnelles des années 1980 affirmaient tous ceci : si vous voulez quelque chose de rapide, passez à l'assembleur.

Que signifie utiliser l'assembleur, et en quoi c'est différent du BASIC ? Pourquoi est-ce que c'est plus rapide ? Était-ce vraiment la seule solution ? C'est ce que nous allons voir dans cet article et les suivants.

J'ai tenté plusieurs approches pour arriver au premier programme en assembleur dans une série d'articles. Et j'en suis arrivé à la conclusion qu'il n'y a pas moyen de passer outre quelques explications rapides des constituants de l'ordinateur et de leurs fonctionnements.

On va tout de même garder une vue large et schématique pour la plupart des composants. Pour le microprocesseur, un Z80 sur le VG5000µ, il faudra descendre un peu vers le fonctionnement de la puce, sans y sombrer.

En effet, programmer en assembleur, c'est programmer la machine au plus près, suivant ses caractéristiques, sans l'aide d'un langage de programmation offrant des abstractions.

La machine, en très bref

Le VG5000µ est composé de :

  • Un microprocesseur Z80A, que je désignerai plus simplement comme Z80, qui est le nom générique pour cette série. Le microprocesseur est souvent désigné comme le cœur de l'ordinateur. Je préfère le désigner comme chef d'orchestre. C'est ce composant qui exécute les instructions du programme.
  • Un clavier, qui est une série d'interrupteurs agencés sous forme de matrice dont l'état peut-être lu grâce au contrôleur d'entrée/sortie du Z80.
  • Une mémoire au contenu figé (ROM) de 16ko, qui contient le programme de gestion de la machine.
  • Trois mémoires vives (RAM) de 8ko, contenant toutes les données dynamiques de la machine. Deux de ces mémoires servent au fonctionnement général, la troisième est réservée au fonctionnement du processeur graphique.
  • Un processeur graphique, EF9394, qui gère l'affichage.
  • Une interface cassette.
  • Des BUS et des circuits logiques pour relier le tout.


Schéma simplifié VG5000

Le fonctionnement du CPU, en très bref

Au démarrage de la machine, le Z80, alimenté, va entrer dans une boucle d'exécution jusqu'à son extinction :

  • Acquérir une instruction à l'adresse mémoire de l'instruction suivante (adresse 0 au démarrage).
  • Changement de l'adresse de l'instruction suivante.
  • Exécution de l'instruction acquise.

À cela s'ajoute le traitement des interruptions. Lorsque le processeur reçoit une interruption, l'adresse mémoire de l'instruction suivante est forcée à une valeur spécifique. Une instruction dédiée permet de reprendre plus tard l'exécution là où elle avait été interrompue.

Boucle du CPU

C'est une vue un simplifiée du fonctionnement du Z80, je laisse de côté les détails, comme le fait que l'acquisition d'une nouvelle instruction n'attend pas la fin de l'exécution de la précédente. D'un point de vue logique, en ce qui nous concerne, cela revient au même.

Voyons les étapes plus en détails.

Acquisition de l'instruction

Le Z80 est relié via trois BUS aux mémoires du VG5000µ, exception faite de la mémoire dédiée au processeur graphique. Un BUS, c'est tout simplement une série de conducteurs électriques (disons, des fils) qui permettent à différents composants de communiquer.

Pour acquérir son instruction, le Z80 va utiliser un premier BUS, celui d'adresse, pour signaler de quelle adresse mémoire l'instruction courante est voulue. Puis, via un second BUS, celui de contrôle, le Z80 signal qu'il veut lire le contenu à cette adresse. Après une brève attente, le troisième BUS, celui de données, pourra être lu et contiendra l'information recherchée, fournie par l'une des mémoires.

Une instruction complète pour un Z80 peut être composée d'un ou plusieurs octets. Dans le cas d'instructions à plusieurs octets, ceux-ci seront demandés les uns après les autres.

Exécution de l'instruction

Une fois l'instruction acquise, celle-ci est décodée et exécutée. Une instruction en langage machine Z80 est une suite de 1 à 4 octets. Chaque octets est une série de 8 informations binaires. Ces informations binaires, au niveau du microprocesseur, sont des informations électriques : est-ce que le signal est haut (1), ou bas (0) ?

La manière dont est architecturé le Z80 fait que ces signaux activent à leur tour d'autres signaux, qui provoquent le transfert d'information à travers les circuits internes au Z80. Ces circuits internes peuvent être des mémoires (les registres), des unités de calculs simples, des unités de calculs et de logique. Les signaux peuvent aussi atteindre les BUS pour émettre des informations ou en recevoir.

Ainsi, par exemple, l'instruction de retour d'un sous-routine, dont le nom est 'RET', se compose en langage machine des signaux suivants 11001001. C'est une instruction sans argument qui déclenche une série de micro-actions . La première est de demander à la mémoire le contenu à l'adresse désignée par le registre SP, qui est un registre dédié à ce genre d'opérations, tout en augmentant la valeur de SP de 1. La seconde est identique : demander le contenu mémoire à l'adresse SP nouvellement modifiée tout en l'incrémentant de 1.

Le résultat de ces deux octets obtenus est placé dans le registre PC, qui est le registre qui désigne l'instruction suivante à obtenir.

Ouf !

C'est un peu lourd ? Voilà ce qu'il faut retenir : une instruction en langage machine déclenche une série de micro instructions influant les composants internes du microprocesseur.

C'est justement parce que tout ce détail est encombrant pour réfléchir à la résolution d'un problème que nous allons vite monter d'un cran en abstraction, et passer à l'assembleur, dans le prochain article.