Dans le dernier article, j'avais cherché une version plus rapide pour effectuer une division par 3, toujours dans l'optique d'afficher un point à l'écran en transcrivant la routine écrite en BASIC vers de l'assembleur Z80.
Le résultat était mitigé : une routine en moyenne plus rapide et plus stable, mais sur le domaine de définition considéré (le nombre de lignes graphiques du VG5000µ), pas entièrement gagnante.
Dans cet article, je vais donc étudier une autre manière de faire, un peu différente. Alors que les deux premières implémentations permettait de diviser par n'importe quel nombre de 1 à 255, cette nouvelle version est spécialisée dans la division par 3.
Est-ce que cette spécialisation permettra de gagner en performance et/ou en taille ?
L'idée
Le Z80 n'a pas d'instruction pour diviser de manière générale, cela a déjà été mentionné dans les articles précédents. Par contre, il est tout à fait possible de …
Dans le dernier article, j'avais écrit une première manière d'effectuer une division, en spécialisant la routine pour une division par 3 puisque c'est ce qui m'intéresse pour afficher un point à l'écran du VG5000µ.
Pour référence, cette routine nécessitait 15 octets en mémoire et son exécution pouvait prendre jusqu'à 695 cycles, ce qui est plutôt grand.
Micro optimisation
La première optimisation est une micro optimisation. On appelle micro optimisation une amélioration de la routine par un détail de fonctionnement, plutôt que par une réflexion sur l'ensemble de la méthode.
Ici, l'idée est de remplacer le couple push bc / pop bc en début et fin de la routine par un couple exx / exx. L'instruction exx du Z80 effectue un renommage des registresBC, DE et HL. Ces registres (ainsi que d'autres, mais qui ne sont pas touchés par cette instruction) existent en deux exemplaires dans le Z80. Un exemplaire de chaque …
La semaine dernière, profitant d'un voyage à San Francisco, j'ai allongé un peu mon séjour pour pousser jusqu'à Mountain View et aller visiter un musée qui semblait fort intéressant. Le Musée de l'Histoire des Ordinateurs, ou dans le texte « Computer History Museum »
Première chose à savoir si vous êtes à San Francisco même, que vous choisissiez le train (pas cher, mais long, avec changement) ou la voiture (plus cher, un peu moins long), prévoyez le trajet pour ne pas arriver trop tard. En effet, le musée ferme assez tôt : 17h.
En voiture, tant qu'à visiter, vous pourrez faire un détour par la 280 pour passer par des endroits sympas ou la 1 pour des endroits encore plus sympa, à l'aller ou au retour. Ou opter par la 101 pour aller au plus direct (mais potentiellement aussi plus encombrée, vérifiez avant de partir).
À présent que j'ai un garde fou pour vérifier que je ne fais pas d'erreur d'inattention, me voilà près à diviser des nombres. Pour rappel j'ai besoin de diviser des nombres afin de faire les calculs permettant d'affiche le bon pixel à l'écran.
Pour second rappel, le Z80, au cœur du VG5000µ (et de beaucoup d'autres ordinateurs de l'époque) n'a pas d'instruction de division.
La division
Lorsque je divise de manière entièrea par b, je veux trouver le nombre c tel quel \(c * b = a\). Comme la division ne tombe pas toujours juste, j'ai aussi un rester tel que \(c * b + r = a\).
Autrement dit, combien de fois dois-je additionner b pour obtenir a (au reste près). Une manière de trouver le résultat est de soustraireb à a autant de fois que l'on peut sans passer sous 0.
Par exemple, \(\frac{21}{7}\) se trouve comme ceci …
Après avoir mis en place une vérification (légère) de l'intégrité de la pile, je passe à la vérification de la validité de l'appel d'une fonction.
Le fonctionnement du test est assez simple : je prends une suite de nombres, j'appelle une fonction avec en paramètre chacun de ces nombres, je vérifie que le résultat est conforme à ce que j'attendais.
Par exemple, si je veux tester une fonction diviser par 2 (division entière), je peux utiliser la suite de nombre 0, 10, 32, 255 et comparer les résultats respectifs avec 0, 5, 16, 127 (255 étant impair, le résultat de la division entière est 127, avec un reste égal à 1).
Encore plus simple qu'une division par 2, il y a la fonction identité : celle qui renvoie le paramètre sans le toucher. Tester cette fonction permet de se concentrer sur le développement du test.