Depuis le début de l'implémentation de ce Forth sur 6502, j'ai parlé de « pseudo mots ». Ces mots ont un CFA (Code Field Address) et un PFA (Parameter Field Address), mais pas d'entête de mot ni de principe de dictionnaire.
Or pour qu'un mot soit complet en Forth, il faut ces deux autres concepts. Dans cette implémentation je vais utiliser deux autres sections : le NFA (Name Field Address) et le LFA (Link Field Address).
Ce qui donne la structure complète suivante :
NFA : entête du mot, dont le premier octet est la longueur du nom du mot, suivi du nom lui-même. Seuls les 5 bits de poids faible sont utilisés pour la longueur (ce qui limite la longueur des noms à 31 caractères). Le bit de poids fort est toujours à 1, les deux autres bits seront vus plus tard. De plus, le dernier octet du nom a …
Jusqu'à présent, la boucle principale du programme en Forth était basée sur un hack. Ce hack consistait à réinitialiser l'IP (Instruction Pointer) à la fin du traitement. C'est un peu comme si à chaque fois qu'on avait fini le traitement, on relançait le programme depuis le début.
Il est temps d'implémenter un nouveau mot Forth : BRANCH. Ce mot, suivi dans le PFA par un offset, opère un saut inconditionnel en additionnant cet offset à l'IP courant. En choisissant un offset négatif, l'exécution va revenir en arrière et donc créer une boucle infinie.
Le pseudo code est le suivant :
(IP) -> X lit l'offset pointé par l'Instruction Pointer
L'IP ayant été positionné sur l'emplacement après le mot BRANCH
par NEXT.
IP + X -> IP ajoute l'offset à l'IP
NEXT appelle NEXT pour continuer l'exécution
Nous y voilà ! Après avoir mis en place un framework de tests dans l'article précédent, il est temps d'implémenter le mot NEXT.
Un petit rappel du premier article de Moving Forth : NEXT est le mot qui permet de faire avancer l'exécution d'une séquence de pointeurs vers des mots Forth. Son pseudo-code (en modèle Indirect Threaded Code) est le suivant :
En 6502, le code est un peu long, car l'adressage indirect nécessite de passer par des registres en page zéro. Et les manipuler demande plusieurs instructions. Je …
Depuis le dernier article, je me suis surtout concentré sur la mise en place d'un framework de tests, ainsi que sur une réflexion de « comment commencer » ?
La lecture de l'article 2 de Moving Forth m'a donné une liste de mots à implémenter en priorité : NEXT, DOCOL et ;S. Cela afin d’arriver rapidement sur une boucle écrite en Forth. J'y reviendrai plus loin dans l'article.
Côté tests, ça a été une aventure en plusieurs étapes. Dans l'idée d'augmenter le nombre de tests, je voulais m'appuyer sur un framework de tests LUA tout fait. J'en ai trouvé un, luaunit qui m'a semblé tout à fait répondre à mes attentes. Pour l'utiliser, je dois utiliser un require("luaunit") dans mon script de tests. Et là ont commencé les ennuis. Tout d'abord, require() n'est pas permis par défaut dans Mesen2, il faut aller permettre les fonction E/S dans les …
Avant de passer à la lecture de l'article 2 de la série Moving Forth, je veux mettre en place un projet « minimal ». Plus exactement, c'est initialement ce que je voulais faire, avec un petit code source pour Famicom qui affiche un texte, un Makefile et bien entendu, un framework de tests.
Mais les notes que j'avais prises sur la Famicom remontaient à un petit moment, et il y a quelques trucs à initialiser avant d'afficher un caractère à l'écran. J'ai donc cherché un squelette de projet déjà fait. Sur une machine populaire, ça doit bien
exister.
Mon choix s'est porté sur Nes Template de Mike Moffitt. Le squelette n'est
pas minimaliste, mais a une bonne base, avec un système de configuration flexible pour la ROM destination, et assez de quoi
écrire un message à l'écran, ainsi que manipuler des banques de mémoire. C'est bien écrit, bien …