Revenir au plan du site


Afficher un caractère en programmation système et hardware


Si vous n'avez pas encore commencé à lire la présentation de l'assembleur Z80 ou que vous ne connaissez pas l'assembleur, il n'est pas nécessaire de le connaitre pour lire cet article. Le but de cette présentation est uniquement de montrer comment des programmes fonctionnent, quelles sont les avantages et inconvénients de tel ou tel type de programmation.

Voici l'affichage du mot CPC suivi d'un retour chariot en programmation système. On voit que le programme est très simple et qu'une fonction est dédiée à l'affichage des caractères. ce programme va fonctionner dans toutes les résolutions de sortie (basse, moyenne, haute) et avec toutes les encres possibles. Les routines sont très flexibles mais ça se paie au prix fort.
ld A,'C' : call #BB5A ; le vecteur #BB5A permet d'afficher le caractère
ld A,'P' : call #BB5A ; dont la valeur ASCII est dans le registre A
ld A,'C' : call #BB5A
ld A,10 : call #BB5A
ld A,13 : call #BB5A
ret


Pour la forme, nous allons créer une fonction qui n'existe pas dans le système, afin d'afficher une chaine de caractères et s'arrêter au caractère zéro.
ld hl,message
affiche_chaine
  ld a,(hl) : inc hl ; récupérer la valeur dans le tableau et incrémenter le pointeur
  or a : ret z ; est-ce que la valeur est zéro? Si oui on sort
  call #BB5A ; afficher le caractère
  jr affiche_chaine
message defb 'CPC',10,13,0

Que se passe-t'il si nous devons tout faire nous même? Hé bien pour commencer, il va nous falloir une fonte de caractères! Le système utilise celle stockée dans la ROM qui est une fonte prévue pour la haute résolution, le mode 2. À partir de cette fonte, le système est capable de la reconstruire pour les autres résolutions, tout en ajoutant un système complexe afin de gérer chaque encre.
Nous concernant, l'exemple suivant s'appliquera au mode 1. Nous pouvons récupérer la routine affiche_chaine mais il faudra effectivement afficher le caractère à un moment ou un autre!
ld hl,message
affiche_chaine
  ld a,(hl) : inc hl ; récupérer la valeur dans le tableau et incrémenter le pointeur
  or a : ret z ; est-ce que la valeur est zéro? Si oui on sort
  push hl : call affiche_caractere : pop hl ; on a besoin de conserver notre pointeur HL
  jr affiche_chaine
message defb 'CPC',0

affiche_caractere
ld h,0 : ld l,a : add hl,hl : add hl,hl : add hl,hl : add hl,hl ; nos caractères font 16 octets
ld bc,fonte : add hl,bc ; HL=adresse des données du caractère dans le tableau fonte
ld de,(position_char) ; on récupère la position du curseur
; et on affiche
ld xl,8 ; sur 8 lignes, nous pouvons utiliser IX ^_^
ld bc,#800-1 ; pour passer à la ligne suivante et revenir sur l'octet d'avant
affiche_ligne_caractere
ld a,(hl) : inc hl : ld (de),a : inc de ; lecture du premier octet et écriture à l'écran
ld a,(hl) : inc hl : ld (de),a ; lecture du deuxième, écriture à l'écran
ex hl,de : add hl,bc : ex hl,de ; on ajoute BC à DE (on permute deux fois HL et DE pour faire l'addition)
; le retour à la ligne est fait, on peut continuer
dec xl : jr nz,affiche_ligne_caractere
; terminé, il faut avancer notre curseur
ld hl,(position_char) : inc hl : inc hl : ld (position_char),hl
ret

position_char defw #C000
fonte ; données de la fonte

Notre routine d'affichage est très simple, le code n'est pas énorme (il serait un peu plus long avec des optimisations...) Elle ne gère pas le retour chariot, c'était pour donner une idée de la complexité qu'il y a à se passer du système. Maintenant, nous allons réaliser une mesure du temps nécessaire pour exécuter nos deux programmes. Dans un souci d'équité, la mesure du programme système ne concerne que les trois premiers caractères, je n'ai pas mis le retour chariot.

Temps d'éxécution du programme pur  système : +9000 nops
Temps d'éxécution du programme pur hardware : 800 nops


On est quand même sur un facteur 10 en vitesse...