Ceci est le premier article de la série 161eForth v0.5b, se terminant ici: habr.com/en/post/452572Le traducteur EFORTH est maintenant également sur la calculatrice domestique MK-161 Electronics! Le 17 mai, la version v0.5b a réussi mes tests, ainsi que cinq tests de création TEST-TEST4. J'ai réalisé ce qui peut être fait seul, mais je pense que ce n'est que la moitié de la bataille. Il est temps de présenter un nouvel outil à la communauté en ouvrant le code 161eForth pour les tests publics. J'ai une liste de ce qu'il faut améliorer et où «travailler sur la stabilité». Vos suggestions et commentaires seront pris en compte lors de l'achèvement du travail et de la version 1.0
Lors du portage de la dernière version d'eForth sur la plate-forme nationale, deux obstacles ont été surmontés avec succès - la vitesse relativement faible de la machine 8 bits, qui est programmée dans son propre langage d'entrée, et la modeste quantité de mémoire binaire disponible (voir 2.4.1), seulement 4096 octets.

Lors de l'écriture de 161eForth, des solutions toutes faites préparées pour Callisto, le langage d'entrée de nouvelle génération pour les PMK domestiques, ont été utilisées. Il s'agit d'une technologie pour implémenter une machine fort au-dessus de l'ALU décimal et de l'architecture «Harvard», des pilotes de console et une disposition de clavier alphanumérique, ainsi qu'un terminal logiciel basé sur eux, fonctionnant via le port série RS-232. En plus de l'électronique MK-161 et de la distribution 161eForth, vous aurez peut-être besoin d'un clavier patch fait maison où les lettres des alphabets russe et anglais sont signées sur les touches. Les lettres sont classées alphabétiquement ligne par ligne, de gauche à droite et de haut en bas.

Le Dr Chen-Hanson Ting, auteur de versions modernes d'eForth, souligne dans son livre [1] l'importance de comprendre les deux composantes du fort. Il s'agit d'un interprète interne ("adresse") qui permet à l'équipement d'exécuter le code cousu de Fort, et d'un interprète externe ("texte") responsable du dialogue avec une personne.
Dans deux articles, je m'attarderai en détail sur les solutions les plus radicales utilisées dans la mise en œuvre de chacun de ces deux interprètes chez Electronics. L'apprentissage de ces solutions peut être utile et inspirant pour migrer eForth vers d'autres appareils avec une mémoire et des performances limitées. La compréhension des articles aidera à une introduction initiale aux microcalculateurs programmables (PMC) et à Fort. Je vais vous expliquer les moments difficiles propres à Electronics MK et au traducteur eForth.
Pour commencer, les mots eForth sont divisés en général et systémique.
La taille des lettres est importante. Les noms des mots ordinaires sont définis en lettres majuscules et en minuscules système. J'ai également fait mes innovations dans eForth en minuscules. L'auteur d'eForth suggère de mener le dialogue principal en mode CAPS. Lorsque vous devez utiliser le mot système, changez l'heure en lettres minuscules (combinaison de touches FP).
Dans l'article, tous les mots sont écrits en majuscules pour se démarquer du texte. Dans plusieurs premières implémentations eForth, les en-têtes de mots système ont été exclus et non émis par la commande WORDS. Cela a contribué à simplifier l'apparence d'eForth et à attirer l'attention de ceux qui utilisent Fort pour la première fois. Dans 161eForth, les titres de ces mots ont été enregistrés principalement en raison de la présence du décompilateur de mots deux points SEE (voir la vidéo n ° 3 à la fin de l'article), qui n'affichera pas les noms des mots système si leurs titres sont supprimés.
Pour rationaliser l'article et le rendre utile comme référence, j'ai dû utiliser plusieurs termes avant de les définir. Les professionnels de Fort et PMK doivent être familiarisés avec ces termes. Les débutants doivent parfois regarder dans les sections voisines (j'ai mis les liens aux bons endroits) ou relire l'article plusieurs fois.
161eForth lui-même est présenté ici, avec le texte source, un clavier graphique à l'écran et l'aide words.txt avec une description de tous les mots implémentés:
http://the-hacker.ru/2019/161eforth0.5b.zipJ'ai également posté 5 petites vidéos sur YouTube illustrant le fonctionnement du 161eForth pour ceux qui n'ont pas le MK-161. Vous pouvez
regarder l'intégralité de la playlist sur YouTube . Ci-dessous est le premier d'entre eux, les 4 restants à la fin de l'article.
eForth et sa mise en œuvre
eForth a été conçu comme un remplacement moderne du traducteur fig-Fort très connu. Pour passer au MK-161, j'ai choisi une version 32 bits 5.2 du traducteur 86eForth avec code cousu indirect, écrite en 2016 sur l'assembleur MASM pour le système d'exploitation Windows. Cette version est décrite en détail dans la troisième édition d'eForth et Zen [1]. Ceux qui connaissent l'anglais, je vous conseille de trouver et d'étudier ce livre, il est très utile pour comprendre 161eForth.
Dans une lettre personnelle, l'auteur a confirmé que 86eForth502.asm de ce livre est la dernière version d'eForth. Sur Internet, vous pouvez trouver de nombreuses informations en anglais à ce sujet et sur les versions précédentes d'eForth.
Le développement d'eForth a suivi une voie scientifique enseignée par le professeur Wirth en utilisant l'exemple de son langage de programmation Oberon. Chaque version ultérieure d'eForth était une simplification de la version précédente. Tout ce qui peut être dispensé a été retiré de la langue. Il reste un ensemble soigneusement pensé de constructions langagières fortes et expressives, dont la puissance a été testée sur plus de 40 implémentations eForth pour diverses plates-formes. Maintenant sur la calculatrice!
Étant un dialecte minimaliste de Fort, eForth n'a pas pour objectif de gagner la course contre le plus petit Fort. L'ensemble de mots qu'il propose est assez pratique et peut facilement être étendu par le programmeur dans le sens nécessaire à ses tâches.
La première version d'eForth a été publiée en 1990 dans l'assembleur MASM pour les processeurs 8086 et fonctionnait sous MS-DOS. Il contenait 31 mots de base dépendant de la machine et 191 mots de haut niveau. L'idée était simple: vous ne traduisez que 31 mots dans votre assembleur et obtenez immédiatement eForth sur votre ordinateur.
Cette approche a été critiquée sur Internet, car la façon de minimiser le nombre de mots dans l'assembleur a conduit à des performances extrêmement faibles pour les systèmes embarqués. Déjà dans la deuxième version d'eForth, le nombre maximum de mots a commencé à être implémenté dans l'assembleur, ce qui a redirigé l'inclinaison vers non seulement un portable facilement, mais aussi un système de programmation pratique.
Pendant plusieurs années, Bill Munch, l'auteur original d'eForth, et son collègue le Dr Chen-Hanson Ting ont publié leurs versions eForth en parallèle. Chaque version avait ses propres caractéristiques. Les options eForth pour différentes plates-formes ont également été intégrées par d'autres programmeurs.
La version 5.2, publiée en 2016, contient 71 mots de «code» et 110 mots de «deux points». Un quart de siècle de recherche de l'idéal a permis de réduire considérablement le nombre total de mots. Dans le même temps, pour des raisons de performances, le pourcentage de mots mis en œuvre à un faible niveau a augmenté.
Le 161eForth proposé bénéficie des avantages généreux de ces progrès, mais ne prétend pas développer davantage la ligne principale. Mon implémentation fournit au programmeur tous les outils présents dans la version 5.2. Lorsque l'architecture MK-161 rend l'implémentation de certains mots 86eForth impossible ou vide de sens, au lieu de jeter l'excédent, je donne aux programmeurs un remplacement complet, en le prenant de la norme ANSI / ISO [4]. Ceux qui recherchent le minimalisme peuvent indépendamment jeter des mots «supplémentaires», car par tradition 161eForth est livré avec du code source.
Lors de la mise en œuvre d'eForth, j'ai adhéré à la compréhension de l'auteur. Par exemple, à mon avis, une boucle FOR NEXT avec une valeur initiale de n devrait s'exécuter exactement n fois. La même conclusion est finalement arrivée à Chuck Moore, l'auteur des langues Forth et colorForth. Malheureusement, eForth utilise une convention obsolète et exécute un tel cycle n + 1 fois, avec un compteur de n à 0. Je n'ai pas corrigé cela et plusieurs autres lacunes, préférant la compatibilité de 161eForth avec les implémentations pour d'autres plates-formes.
Étant donné que 161eForth est le premier système de programmation embarqué pratique pour l'électronique MK-161, à l'exception de la langue d'usine, j'ai retracé la longue histoire d'eForth et j'ai renvoyé quelques mots à la langue qui était utile sur d'autres plates-formes et qui peut être demandée maintenant.
Par exemple, la nouvelle ancienne variable 'BOOT contient le jeton (voir 3.1) du mot, qui est exécuté d'abord après l'initialisation de l'environnement, mais avant le début du dialogue. Par défaut, 'BOOT contient un jeton TLOAD pour interpréter le code de la "zone de texte" (voir 2.4.2). Cela permet au programmeur de personnaliser eForth pour lui-même sans recompiler l'environnement, ce qui est toujours impossible à produire à bord de l '«électronique».
Les tâches prioritaires de l'implémentation étaient la sauvegarde de la mémoire binaire (voir 2.4.1) et l'amélioration des performances. Leur solution a entraîné une diminution spectaculaire du nombre de mots de haut niveau, car leur code occupe cette précieuse mémoire, en raison d'une augmentation du nombre de mots de base rapides implémentés dans la mémoire de programme bon marché (voir 2.4.3).
Par conséquent, 161eForth contient 129 mots de code, 78 mots de haut niveau et occupe 1816 octets de mémoire binaire MK-161, soit moins de la moitié. Cela donne de l'espoir pour la métacompilation de sa partie de haut niveau directement à bord de l'électronique.
Le code source de l'eForth MK-161 est divisé en deux grandes parties. Le noyau écrit dans le système de commande MK-161 est contenu dans le fichier eForth0.mkl. Les mots de haut niveau sont définis dans SP-Forth et placés dans le fichier eForth.f.
La distribution a également un fichier d'aide words.txt, qui documente tous les mots 161eForth avec la notation de pile et une brève explication, en une seule ligne.
1.1 Le code source du noyau eForth0.mkl
Le noyau eForth contient du code exécutable opérant dans la mémoire des programmes MK-161 (voir 2.4.3), qui est compilé sur un ordinateur dans le fichier eForth0.mkp par des moyens standard, par exemple, le compilateur propriétaire MKL2MKP.
Le code source du noyau contenu dans le fichier eForth0.mkl est écrit en
mnémoniques latins . Par exemple, une commande IPE pour lire le registre E (aka R14) est écrite dans ce mnémonique comme RME. Étant inhabituel pour les propriétaires de PMK soviétique, les mnémoniques latins sont pratiques pour taper à partir d'un clavier d'ordinateur. En effet, il est plus facile de taper des FX ^ 2 bizarres que des Fx² familiers.
Le fichier eForth0.mkp est un préréglage du noyau. En plus du code des primitives, il contient un en-tête de noyau et une table de noms tblNames, que eForth.f transfère lors du décodage vers des registres décimaux (voir 2.4.4). C'est sur la base de eForth0.mkp que le noyau eForth.mkp sera créé (voir 2.4.3), donc eForth0.mkl doit d'abord être compilé.
1.2 Code source des mots de haut niveau eForth.f
Le fichier eForth.f est alimenté à l'entrée du merveilleux compilateur domestique SP-Forth [5]. Le fichier contient les définitions de tous les mots de haut niveau. Au fil du temps, ils peuvent être identifiés sur l'eForth lui-même et éventuellement compilés directement à bord de l'électronique MK-161.
Pendant la compilation, eForth.f lit le noyau vierge eForth0.mkp et avec son aide crée trois fichiers dans le répertoire courant pour un chargement ultérieur dans MK-161: eForth.mkp, eForth.mkd et eForth.mkb. C'est eForth.mkb qui contient les corps des mots de haut niveau, bien que leurs en-têtes se trouvent dans le fichier eForth.mkd.
Le quatrième fichier, eForth.mkt, est écrit manuellement dans eForth et peut être modifié à bord du MK-161 à l'aide de l'éditeur de texte intégré. J'analyserai chacun de ces quatre fichiers plus en détail ci-dessous (voir 2.4).
2. Électronique MK-161
Un fabricant de Novossibirsk appelle le MK-161 un vieil acronyme. C'était le nom des toutes premières calculatrices de l'URSS. Le système d'instruction MK-161 hérite du système de commande des calculatrices soviétiques "Electronics B3-34" et "Electronics MK-61". Cela signifie que les programmes écrits pour les calculatrices soviétiques iront sur le MK-161 sans changements ou avec des changements mineurs.
L'inverse n'est pas vrai. eForth n'ira pas au PMK soviétique, car utilise beaucoup de ressources qui sont apparues pour la première fois dans le MK-152/161 et n'étaient pas disponibles dans les modèles précédents de la série.
Considérez les caractéristiques du langage d'entrée et de l'architecture du MK-161, qui ont influencé 161eForth (ci-après simplement eForth) et ont donné à la mise en œuvre discutée d'eForth un "accent russe".
La première de ces caractéristiques est l'
accord «senior at junior address», qui est systématiquement maintenu dans MK-161. Par exemple, le nombre 1000 = 3 × 256 + 232 sera écrit sur deux octets consécutifs, comme 3 et 232.
2.1 Adressage indirect
Programmation Le PMK soviétique a entendu parler de l'adressage indirect. Pour
l'adressage direct, nous indiquons explicitement le numéro de registre auquel nous nous référons. Par exemple, P IP 44 considère le contenu du registre 44. La clé P qui est apparue dans MK-152 est utilisée pour accéder aux registres avec le numéro 15 ou plus - ces registres étaient absents dans la PMK soviétique.
En
adressage indirect, le numéro du registre requis n'est pas connu à l'avance. Ce numéro est dans un registre différent. Par exemple, si le registre 8 contient le numéro 44, la commande K PI 8 considère le contenu du registre 44 (R44).
Les touches K et P peuvent être combinées. Par exemple, la commande R K BP 20 transférera le contrôle (GOTO en mnémoniques latins) à l'adresse stockée dans R20.
La caractéristique qui s'est avérée importante pour l'interprète eForth interne est liée à l'augmentation / diminution préliminaire des registres lors de l'adressage indirect. Cette fonctionnalité est héritée du PMK soviétique.
Par exemple, les commandes de lecture indirecte KI 0, KI 1, KI 2 et KI 3 réduisent de un le contenu des registres 0, 1, 2 ou 3 au registre souhaité. Les commandes KI 4, KI 5 et KI 6 avant de lire, augmentez le contenu des registres 4, 5 ou 6 d'une unité.
Cette «modification» du registre d'adresses vous permet de traiter des groupes entiers de registres en boucle. Il est similaire à ++ R et --R en C. Le numéro de registre du registre est important. C'est lui qui détermine s'il va augmenter (registres 4-6) ou diminuer (registres 0-3) avec adressage indirect.
L'architecture 161eForth a été affectée par le fait que l'augmentation des registres 4-6 à adressage indirect est
préliminaire . Par conséquent, le pointeur d'interprétation (IP) situé dans R6
pointe toujours
vers le dernier octet du code cousu. Dans 86eForth, IP indique toujours un octet suivant qui n'a pas encore été lu.
Cela est également vrai pour le pointeur de pile de retour (RP) stocké dans le registre 2. R2 pointe toujours vers le haut de la pile de retour.
Une caractéristique utile du MK-161 est l'absence d'augmentation / diminution du registre si un adressage indirect se produit avec la nouvelle clé R. Par exemple, RKIP02 compte le nombre du haut de la pile de retour sans changer le pointeur. Il s'agit d'une équipe Fort R @ prête à l'emploi. De ce qui précède, il s'ensuit que la valeur lue est inférieure de un à l'adresse du jeton suivant, qui sera exécutée après le retour du mot "deux points".
Lorsque vous devez développer ou étudier des mots qui interagissent étroitement avec l'interprète interne eForth, assurez-vous de bien comprendre ce point subtil associé à l'
exagération .
2.2 Tableaux, ordonnés et associatifs
Les tables MK-161 sont situées dans la mémoire du programme (voir 2.4.3). Ils sont apparus dans le "Electronics MK" de Novossibirsk et sont totalement inconnus des experts du PMK soviétique. L'adresse de la table utilisée est toujours stockée dans le registre 9042, mais leur accès est différent.
Une table ordonnée est un tableau d'entiers 16 bits non signés. eForth contient une telle table tblTokens avec les adresses des primitives (voir 3.1.1) - Mots forts écrits dans le système de commande MK-161. L'interpréteur d'adresses (voir 3.2) utilise tblTokens pour exécuter rapidement le code cousu, eForth essaie donc de toujours contenir l'adresse de cette table dans R9042.
Pour accéder à une table commandée, vous devez écrire le numéro de l'article souhaité dans R9210. Le nombre n dans le registre X sera remplacé par la valeur de l'élément de table par le nombre n, le décompte part de zéro.
Les tableaux associatifs ("recherche par valeur") sont activement utilisés par eForth, principalement par la primitive (FIND), à la recherche d'un mot par son nom. De plus, la table associative tblCHPUT est utilisée lors de l'impression de lettres à l'écran pour traiter les sauts de ligne et autres codes de contrôle.
Pour rechercher l'élément n dans le tableau associatif, écrivez n à R9212. Le nombre n dans le registre X (la direction l'appelle l '«index») sera remplacé par la valeur de 16 bits enregistrée dans le tableau immédiatement après son «index» n.
La présence de cette fonction de recherche rapide, quoique simple, implémentée en langage assembleur dans le «firmware» MK-161 a aidé eForth à obtenir des performances acceptables lors de la reconnaissance des noms de mots et de la compilation des programmes. Bien sûr, pour cela, j'ai dû développer non pas les tables de reconnaissance de noms les plus simples, «affûtées» pour cette fonction. Nous en parlerons plus en détail dans le deuxième article.
2.3 Interruptions et console
«MK Electronics» permet à ses propriétaires d'écrire des programmes dans la langue d'entrée qui répondent à certains événements - comme appuyer ou relâcher un bouton, mettre fin au décompte de la minuterie.
eForth utilise activement ce
système d'interruption pour l'entrée au clavier et l'affichage du curseur clignotant lorsque vous y êtes invité, et pour l'entrée / sortie via un port série universel (RS-232).
Les lettres saisies à partir du clavier sont mises en file d'attente bufKbd lorsque vous appuyez sur les touches. Ceci est très pratique et permet de gagner du temps sur les systèmes à faible vitesse. Le changement d'alphabet et de cas est géré par l'interruption KeyPress et ne prend pas d'espace dans la file d'attente. Un appui long sur la touche appelle la répétition automatique.
Lorsque la ligne de 8 lettres est pleine et que eForth n'est pas encore prêt à traiter l'entrée (la situation est très rare), le MK-161 émet un grincement malheureux. Bien sûr, je ne voudrais pas implémenter tout ce travail naturel du clavier dans le traducteur, mais obtenir le MK-161 «prêt à l'emploi» en tant que service du programme intégré (firmware). Mais ce qui, comme on dit, est riche.
Après le début du travail, toutes les sorties eForth sont dirigées vers
l'écran graphique MK-161. La sortie des lettres dessus est effectuée par une routine relativement simple de la CNCut. La seule difficulté ici est l'implémentation du code de contrôle BS, le «space back». MK-161 utilise une police proportionnelle. Par conséquent, dans un tampon spécial tblBS, vous devez vous rappeler les positions des caractères affichés, d'où le code de sortie BS les prend plus tard.
Pendant le dialogue, l'utilisateur peut utiliser le mot IO> pour rediriger toutes les E / S vers le port série RS-232, ce qui permet de programmer le MK-161 à partir d'un clavier d'ordinateur familier ou d'un autre MK-161 . Le mot CON> renvoie le contrôle à la console de calcul.2.4 Zones de mémoire et installation d'eForth sur le MK-161
La mémoire «MK-161 Electronics» se compose d'une mémoire de programme adressable séparément et d'une mémoire de registre de données. À son tour, la mémoire de registre est hétérogène et est divisée en trois grandes zones.Les registres avec des nombres de 0 à 999 stockent des "nombres décimaux". Ce sont des registres ordinaires, comme dans "Electronics B3-34" et autres calculatrices. Ils sont simplement capables de stocker non pas 8, mais 12 décimales de la «mantisse».Les registres avec des nombres de 1000 à 8167 stockent des entiers de 0 à 255. Les 3 derniers kilo-octets de cette zone avec des adresses de 5096 à 8167 sont appelés la zone de texte .Les registres avec des nombres de 9000 à 9999 sont appelés registres de fonction. Cette zone de service de l'espace d'adressage ressemble aux ports d'E / S du microprocesseur. À l'aide de commandes d'écriture et de lecture, ces adresses sont utilisées pour accéder aux périphériques d'E / S, aux systèmes d'interruption, etc.Pour installer eForth sur "Electronics MK-161", il suffit de transférer quatre fichiers vers la calculatrice, par exemple, en utilisant le programme du constructeur MK.EXE:- Écrivez eForth.mkp dans la mémoire du programme à partir de la page 0. La version 0.5b occupe 74 pages.
- Ecrire eForth.mkd dans la mémoire de données décimales
- Ecrire eForth.mkb dans la mémoire de données binaires
- Ecrire eForth.mkt dans la mémoire de texte
Après le transfert vers la calculatrice, je recommande d' enregistrer immédiatement ces quatre fichiers dans un répertoire séparé du «disque électronique» intégré. Puisqu'ils ont le même nom, vous pouvez télécharger eForth immédiatement à la fois en tant que «package».2.4.1 Mémoire binaire ("octet") MK-161: eForth.mkb
Les registres Electronics MK avec des nombres de 1000 à 5095 sont utilisés pour stocker des nombres de 0 à 255. Cette zone de la mémoire de registre de la calculatrice est appelée binaire. Deux registres binaires consécutifs sont accessibles depuis eForth comme une seule «cellule» de 16 bits et (comme partout sur le MK-161), les 8 bits supérieurs sont dans le registre avec un nombre inférieur.eForth utilise cette minuscule «mémoire binaire» comme son principal. Les mots fonctionnent avec elle! et @, ICI et ALLOT, seulement à partir d'ici l'interpréteur d'adresses exécute le code cousu (voir 3.2). Voici les variables eForth, le tampon d'entrée de texte (TIB), le dictionnaire et la pile de restauration tblBS pour implémenter le retour arrière.4096 octets est très modeste, selon les normes modernes. Par conséquent, d'énormes efforts ont été déployés pour apporter à d'autres domaines de la mémoire tout ce qui est possible.2.4.2 Zone de texte: eForth.mkt
Immédiatement après que la mémoire binaire soit une zone de texte , les registres avec des nombres de 5095 à 8167. Techniquement, ce sont les mêmes registres d'octets, mais la possibilité de les écrire sur le disque et de les lire dans un fichier séparé rend cette zone spéciale.Le mot TLOAD est utilisé pour travailler avec «texte» dans eForth. Il alimente toute cette zone à l'entrée de l'interpréteur de texte, sous la forme d'une chaîne de 3072 lettres.Il y a désaccord sur la façon de diviser le texte en lignes. Un éditeur intégré à MK Electronics insiste sur une longueur de ligne de 24 caractères. Callisto utilise la convention Fort, où la chaîne contient 64 caractères. eForth offre à l'utilisateur le choix de compter tout le texte comme une longue ligne. Vous pouvez utiliser l'éditeur intégré MK-161. Vous pouvez écrire le vôtre, compatible avec Callisto.Voici le contenu initial de eForth.mkt, pour plus de commodité, divisé en trois lignes:: hi ." , %user%!" CR ; ' hi 'boot ! hi \
La première ligne définit le nouveau mot hi qui salue l'utilisateur. La deuxième ligne prend le jeton de ce mot (voir 3.1) et le place dans la variable 'BOOT (voir 1). Désormais, la zone de texte cesse de se compiler à chaque démarrage d'eForth. Au lieu de cela, le message d'accueil déjà compilé sera exécuté.
La dernière ligne commence le mot salut, affichant un message d'accueil à l'écran. Le mot \ termine l'interprétation du texte et renvoie le contrôle à la console.
Pour compiler un fichier texte arbitraire, vous devez aller dans la calculatrice avec la commande BYE, aller dans le menu principal et charger le fichier souhaité en mode DOS. Vous pouvez également transférer le fichier mkt depuis un ordinateur. La touche C / P vous ramènera à eForth, après quoi avec la commande TLOAD vous pourrez compiler le fichier chargé dans la zone de texte.
2.4.3 Mémoire de programme: eForth.mkp
La mémoire de programme MK-161 est un espace d'adressage isolé. Il stocke également des octets, mais ils sont en lecture seule. La mémoire du programme contient 10 000 «étapes», qui se sont avérées redondantes pour eForth. Plus d'un quart de la mémoire du programme s'est avéré être libre, ce qui donne une bonne réserve pour le développement du traducteur.
Ce n'est que dans la mémoire du programme que des "mots de code" peuvent être implémentés. De plus, les tables de reconnaissance de nom et toutes les chaînes de texte connues sont affichées ici, ce qui économise de la mémoire binaire.
Certains mots, tels que C @, COUNT et TYPE, peuvent adresser la mémoire de programme si l'adresse n'est pas un nombre positif. Par exemple, la phrase 0 C @ compte comme un «pas» (octet) à partir de l'adresse 0 de la mémoire de programme.
2.4.4 Mémoire décimale: eForth.mkd
Les registres de MK Electronics avec des nombres de 0 à 999 sont appelés décimaux et contiennent des nombres utilisés pour les calculs ordinaires sur la calculatrice - 12 chiffres décimaux de la «mantisse» et 2 chiffres décimaux de «l'ordre». Le fort est conçu pour fonctionner avec des entiers jusqu'à 4 octets de long, une telle ressource est clairement redondante pour eForth.
La mémoire décimale est utilisée pour économiser la précieuse mémoire binaire. Des piles de données et de retours sont effectuées ici. Les en-têtes de mots sont stockés ici - à la fois définis par l'utilisateur et intégrés, un registre par titre. Cette approche vous permet de redéfinir même des mots avec des noms standard.
La pile en mémoire décimale conduit à un certain nombre de caractéristiques caractéristiques du Fort sur le MK-161. Tout d'abord, la plage de valeurs des éléments de la pile est énorme; elle peut accueillir des entiers 32 bits. Le besoin de "doubles entiers" sur le MK-161 disparaît, bien que pour des raisons de compatibilité, j'ai mis en œuvre les mots eForth correspondants. Les «doubles entiers» sont présentés sur MK-161, sous la forme de deux éléments de pile contenant des nombres de 0 à 65535, codant un entier 32 bits avec un signe dans le code supplémentaire. Les 16 bits supérieurs de ce nombre sont placés en haut, c'est-à-dire à l'adresse la plus basse.
Les opérations logiques au niveau du bit AND, OR, XOR et NOT traitent leurs arguments comme des entiers 16 bits. Un résultat de 32768 à 65535 est converti en nombres négatifs de -32768 à -1. Dans eForth, false est codé avec zéro et vérité moins un. Est également vrai toute valeur autre que zéro.
La deuxième caractéristique de la pile de données 161eForth est qu'elle contient des numéros signés. Lorsque le mot @ lit le nombre 65535 dans une «cellule» de 16 bits, il est automatiquement converti en -1. Un
mot spécial «non signé» U @ est prévu pour compter directement 65535, avec un signe plus.
Je rappelle que pour des raisons de vitesse, les
deux éléments supérieurs de la pile de données ne sont pas situés en mémoire décimale, mais directement
dans les registres X et Y.Le fait que les registres décimaux puissent contenir des nombres fractionnaires et des nombres à virgule flottante n'est pas utilisé par eForth. La machine virtuelle eForth utilise ces registres pour stocker des entiers décimaux 12 bits signés. Les registres décimaux sont accessibles par les mots C @ et C! - les mêmes que ceux qui fonctionnent avec des registres uniques.
3. L'interprète interne
Le noyau eForth est un programme écrit dans le langage d'entrée MK-161. Sa première commande MAIN transfère le contrôle au code MAIN, qui découvre tout d'abord les circonstances du redémarrage. S'il a été causé par un mauvais jeton, le MK-161 grincera. Au premier démarrage, et également après avoir allumé le MK-161, l'écran est effacé. Ensuite, MAIN appelle le sous-programme Init pour initialiser le système d'interruption et tout ce dont les pilotes de console MK-161 ont besoin.
Après avoir initialisé les piles de données et les retours, la partie de bas niveau du démarrage est terminée. Des choses incroyables se produisent pour les machines avec l'architecture Harvard - eForth continue d'exécuter du «code câblé» à partir de la mémoire d'octets. L'honneur d'être le premier appartient à un mot dont l'adresse d'en-tête est enregistrée en R43. Il s'agit généralement du mot FROID.
Comment
les mots de haut niveau (IED) sont-ils organisés? Tout mot se compose de deux parties, un corps et un titre.
L'en-tête est stocké en décimal. Il aide l'interpréteur et décompilateur externes à trouver le nom et le corps du mot. L'en-tête contient également
un champ «lexique» - un ensemble d'indicateurs qui aident l'interprète externe à traiter correctement le mot trouvé. L'interprète interne est beaucoup plus important pour le corps VCA situé dans la mémoire binaire et stocké dans le dictionnaire. Il est même capable d'exécuter des mots sans titre.
Le corps du VCA commence par l'octet du
champ de code , qui contient l'adresse du
processeur du mot donné. Quatre gestionnaires VCA sont écrits dans la langue d'entrée MK-161 et commencent sur la première page de la mémoire du programme. Nous les analyserons tous (voir 3.3), mais le principal s'appelle DOLST et se situe à l'adresse 02, immédiatement après la commande MAIN BP déjà considérée. Ce gestionnaire exécute les mots Fort définis avec deux points.
Après l'octet du
champ de code se
trouve un champ de paramètre de longueur arbitraire. Dans les «deux points», le champ de paramètre contient un «code cousu» - une séquence de jetons 16 bits, chacun indiquant une action qui lui est affectée.
Tout d'abord, nous examinerons le jeton plus en détail. Ensuite, nous étudierons l'interpréteur interne INEXT, qui passe d'un jeton à l'exécution du suivant. EForth appelle INEXT un gestionnaire primitif. Nous concluons cette visite de l'interprète interne en analysant les quatre processeurs IED.
3.1 Jetons
Le jeton représente le mot dans le code cousu et la pile, ce qui permet de l'exécuter rapidement. Le jeton est un pointeur vers le corps du mot, mais l'architecture dure du MK-161 a fait ses propres ajustements à cette idée simple. Analysons tous les types de jetons, en commençant par le jeton primitif.
3.1.1 Jeton primitif
Tous les mots inclus dans la distribution eForth sont numérotés de 0 à 206. Cette numérotation est de bout en bout, en tenant compte à la fois des primitives et du VCA. Ceci est fait de sorte que par le numéro du mot, il était facile de restaurer son
nom . Ces noms sont stockés dans la mémoire du programme. Le lien vers le nom souhaité est facilement trouvé dans la table d'en-tête.
Le nombre primitif est son jeton . Comme tout jeton, la primitive prend deux octets dans le code cousu. Le premier est zéro. Le second contient son numéro. La table tblTokens vous permet de trouver rapidement l'adresse du code primitif par ce numéro. L'adresse tblTokens est stockée en permanence dans R9042 (voir 2.2), c'est-à-dire que tout est toujours à portée de main pour exécuter la primitive.
Le mot XT> permet de connaître l'adresse d'un code primitif par son numéro (token). Le code des primitives étant toujours situé dans la mémoire du programme, l'adresse reçue est toujours négative (voir 2.4.3).
3.1.2 Jeton VCA
VCA peut avoir son propre numéro et le nom standard associé, ou il peut être complètement nouveau, créé par l'utilisateur. Dans tous les cas, le
jeton VCA est l'adresse de son champ de code (voir 3), c'est-à-dire un nombre compris entre 1000 et 5095.
Dans le code cousu, le jeton VCA est écrit d'une manière très inhabituelle. Le nombre de centaines (un nombre de 10 à 50) est écrit dans le premier octet, le reste de la division du jeton par 100 (un nombre de 0 à 99) dans le deuxième octet.
Par exemple, le jeton 1234 sera représenté par deux octets 12 et 34. La compilation de celui-ci, et de tout autre jeton, est effectuée en utilisant le mot COMPILE tiré de la norme ANSI. Pour écrire et lire les jetons VCA dans le code cousu, les mots XT! et XT @. Ils accèdent aux adresses (voir 3.1.4), et le mot XT @ est également capable de lire le jeton primitif.
3.1.3 Littéraux entiers
Les littéraux entiers sont une sorte de jetons primitifs. Ils sont suffisamment inhabituels pour être considérés séparément.
Dans le code cousu, les jetons DOLIT et DOLITM occupent quatre octets. Les deux premiers octets contiennent le jeton primitif déjà considéré, c'est-à-dire 0 et le numéro de la primitive. Les deux octets suivants contiennent un entier que le littéral donné mettra sur la pile de données pendant l'exécution.
DOLITM diffère en ce qu'il change le signe du nombre avant de le mettre sur la pile. Il est conçu pour implémenter des nombres négatifs.
3.1.4 Littéraux d'adresse
Comme les littéraux entiers, les trois
littéraux d'adresse BRANCH,? BRANCH et DONXT occupent chacun 4 octets dans le code cousu. Les 2 premiers octets contiennent le jeton primitif, les deux derniers octets sont l'adresse de saut.
L'adresse est enregistrée dans le même format que le jeton VCA (voir 3.1.2). Le premier octet contient le nombre de centaines, le second contient le reste de la division de l'adresse par 100. Je rappelle qu'en raison de l'exagération (voir 2.1), l'adresse de transition ne contient pas l'adresse du jeton souhaité, mais un nombre inférieur à un.
Le jeton DONXT aide à implémenter le «cycle de fin» FOR-NEXT (voir 1). Le saut inconditionnel BRANCH est nécessaire pour implémenter la boucle BEGIN-AGAIN infinie. Branche conditionnelle? BRANCH transfère le contrôle si zéro se trouve en haut de la pile de données (faux). Il sert à implémenter l'instruction conditionnelle IF-THEN, quitte les "boucles indéfinies" BEGIN-UNTIL et BEGIN-WHILE-REPEAT.
3.1.5 Littéraux de chaîne
Les littéraux de chaîne sont un type de jetons VCA. Dans le code cousu d'un littéral de chaîne, après le jeton, il y a un octet avec la longueur de la chaîne, après quoi la chaîne elle-même, du premier octet au dernier.
EForth a trois littéraux de chaîne: $ "| ,." | et abandonner "|. Ils sont définis dans le fichier eForth0.mkl en tant que jetons STRQP, DOTQP et ABORQ, respectivement. Le travail" littéral "principal est effectué par le mot do $ pour eux, le jeton DOSTR.
Pour que la taille de l'article soit raisonnable, je ne peux pas trop m'attarder sur ce sujet intéressant, mais c'est agréable de connaître leur disponibilité dans eForth.
3.2 Interprète d'adresse
Il est temps de considérer
l'interpréteur de jetons , dont l'adresse est toujours écrite dans le registre 9. La plupart des primitives terminent leur travail avec la commande K BP 9, qui transfère le contrôle à l'étiquette INEXT.
INEXT: 6 Fx≠0 NPrime NData: 2 6 + 7 F⟳ 7 8 F⟳ 8
Tout d'abord, l'interpréteur d'adresses lit le premier octet du jeton suivant avec la commande KIP6. S'il est nul, il s'agit d'une primitive et le code sous l'étiquette NPrime gérera le jeton.
L'étiquette NData indique le traitement du jeton VCA. Le premier octet est multiplié par cent par la commande VP 2, après quoi KIP6 + ajoute le deuxième octet du jeton au résultat (voir 3.1.2). Le jeton de lecture est saisi par l'équipe P7 dans le WP «registre de travail» (R7).
Nous savons que le jeton VCA est l'adresse de son champ de code, qui contient l'adresse du processeur. Les commandes KIP7 P8 lisent l'octet du champ de code dans R8, et la commande KBP8 transfère le contrôle au processeur VCA. Le gestionnaire sait que R7 contient un nombre de moins que l'adresse du champ de paramètre du mot en cours de traitement.
Les commandes F⟳ avec le code 25 sont «rangées» sur la pile. Le fait est que eForth stocke les deux premiers éléments de la pile de données directement dans les registres X et Y de la pile MK-161. Une telle solution accélère le travail, mais nécessite de s'assurer que ces données importantes ne sont pas perdues.
Reste à comprendre comment l'interpréteur d'adresses exécute les primitives.
NPrime: F⟳ 6 9210 8 F⟳ 8
La commande KIP6 lit le deuxième octet du jeton primitif. Les commandes RRP9210 P8 lisent l'adresse de cette primitive dans la table tblTokens (voir 2.2 et 3.1.1), et KBP8 transfère le contrôle à cette primitive.
Comme ci-dessus, F⟳ supprime l'excédent de la pile, restituant le contenu des registres X et Y.
L'interpréteur d'adresses eForth est si petit qu'il est dupliqué plusieurs fois dans la mémoire du programme. La copie principale est exécutée par la commande K BP 9, qui complète la plupart des primitives.
Comme exercice, je recommande d'étudier la mise en œuvre du mot EXECUTE, placé après le label EXECU. Il s'agit d'une variante INEXT, qui ne lit pas le jeton dans le code cousu, mais le prend dans la pile de données.
3.3 Gestionnaires VCA
Quatre variétés de VCA ont quatre gestionnaires différents: DOLST, DOVAR, DOCON et DOCONM. Nous avons déjà vu plus haut que l'interpréteur d'adresses avant d'appeler le gestionnaire laisse dans R7 l'adresse du champ de code du mot en cours de traitement.
eForth.f apprend les adresses de ces gestionnaires en lisant l'en-tête du noyau dans le fichier eForth0.mkp. Cela l'aide à compiler correctement le VCA pour l'électronique MK-161 en plaçant le résultat dans le fichier eForth.mkb.
3.3.1 Mots deux points: DOLST et EXIT
Le prochain sujet important après INEXT est ce que fait l'interpréteur interne lorsqu'il rencontre le jeton d'un mot défini par des deux-points. Le champ de code d'un tel mot contient le numéro 2, donc INEXT transfère le contrôle au gestionnaire DOLST, qui effectue le travail nécessaire pour commencer à interpréter la nouvelle liste de jetons.
DOLST: 6 2 F⟳ 7 6 F⟳ INEXT:
Le registre 2, comme nous l'avons déjà expliqué (voir 2.1), contient un pointeur de pile de retour RP. Les commandes IP6 KP2 écrivent la valeur de R6, le pointeur d'interprétation (IP), dans la pile de retour. Plus tard, cela aidera à se souvenir de la position actuelle dans l'ancienne liste de jetons, où INEXT est tombé sur un mot deux-points. IP7 P6 réorganise désormais IP au début d'une nouvelle liste.
Immédiatement après le code DOLST, le code INEXT est placé, ce qui exécutera le premier mot de la nouvelle liste de jetons. Comme ailleurs, les commandes F permettent de maintenir les deux premiers éléments de la pile de données.
Les mots deux-points se terminent généralement par un jeton EXITT, qui fait le contraire, par rapport à DOLST - il prend l'ancienne valeur IP de la pile de retour et revient à l'interprétation de l'ancienne liste de jetons.
EXITT: 02 6 x 1 2 + 2 F⟳ INEXT:
Les commandes RKIP02 P6 lisent l'ancienne valeur IP depuis le haut de la pile de retour (voir 2.1). Après cela, les commandes Cx 1 IP2 + P2 corrigent la valeur de RP, en l'augmentant d'une unité. La commande F⟳ restaure la pile, après quoi INEXT exécute le mot suivant de l'ancienne liste de jetons.
Bien sûr, INEXT ne peut pas aller à la fois après DOLST et après EXITT en même temps. Pour ce faire, j'ai appliqué une ancienne astuce de l'époque de l'URSS. Vous pouvez également le maîtriser en examinant les lignes correspondantes dans le fichier eForth0.mkl.
3.3.2 DOVAR, gestionnaire de variables et de tableaux
Les mots générés par les mots CREATE et VARIABLE utilisent le même gestionnaire DOVAR. Ce gestionnaire pousse sur la pile l'adresse de la variable située dans le champ de paramètre, qui va immédiatement après l'octet du champ de code. Les variables VARIABLE occupent 2 octets et les tableaux créés à l'aide de CREATE contiennent autant d'octets que le programmeur le souhaite.
DOVAR: ⇔ 3 x 1 7 + 9
Les commandes ⇔ KP3 enregistrent le contenu du registre Y dans la pile de données. En même temps, le nombre du haut de la pile est entré dans RY, libérant RX à la nouvelle valeur. Après les commandes Cx 1 IP7 +, cette nouvelle valeur en haut de la pile devient l'adresse du champ de paramètre du mot exécutable. KBP9 transfère le contrôle à INEXT, sans aucune astuce, en passant au mot suivant.
3.3.3 Gestionnaires de constantes: DOCON et DOCONM
Contrairement à DOVAR,
le gestionnaire de constante accède au champ de paramètre de son mot lui-même. DOCON y lit une valeur constante de 16 bits. Cette valeur est toujours positive.
DOCON: ⇔ 3 ⇔ 7 5 x 256 5 × 5 + 9
Les commandes ⇔ KP3 ⇔ enregistrent RY dans la pile de données. Mais cette fois, l'ancien sommet de la pile de données revient à RX. Les commandes IP7 P5 le forcent à revenir dans RY, tout en préparant le registre de pointeur R5 à lire la valeur de la constante. Ensuite, Cx 256 remplace les ordures du registre X par le nombre 256.
Les instruments KIP5 × KIP5 + lisent une constante du champ de paramètres jusqu'en haut de la pile de données, c'est-à-dire en RX. Comme nous nous en souvenons, dans MK-161, le premier octet est toujours élevé. Il est multiplié par 256, après quoi l'octet le moins significatif de la constante est ajouté au produit. Tout le travail est fait, KBP9 transfère le contrôle au mot suivant.
DOCONM fonctionne exactement de la même manière, seul le signe constant après lecture change à l'opposé. Les constantes négatives sont implémentées sur le MK-161 en tant que processeur séparé pour des raisons de vitesse:
DOCONM: ⇔ 3 ⇔ 7 5 x 256 5 × 5 + /-/ 9
Maintenant, nous avons complètement compris comment eForth exécute son code sur l'électronique MK-161 à partir de la zone de données, abordant même un sujet plus profond des littéraux de chaîne (voir 3.1.5).
Dans le deuxième article de la série, je vais parler de l'interpréteur externe de «texte» 161eForth, analyser la structure des tables d'en-tête et la reconnaissance des noms. Cette partie du traducteur m'a demandé de développer des solutions beaucoup plus radicales, dans le contexte desquelles ce qui précède est le Fort traditionnel, ancien et bon.
Programmation Happy Fort!
Littérature
- Dr. Chen-Hanson Ting. eForth et Zen - 3e édition, 2017. Disponible sur Amazon Kindle.
- Baranov S.N., Nozdrunov N.R. Langage fort et sa mise en œuvre. - L.: Génie mécanique. Leningrad Département, 1988.
- Semenov Yu.A. Programmation en langage FORT. - M.: Radio et communications, 1991.
- Norme ANS Forth. X3.215-1994. La traduction
- Documentation SP-Forth .
- Offete Store (Actes du Dr Chen-Hanson Ting) , où vous pouvez télécharger 86eForth v5.2 pour Windows, documentation en anglais.
Illustrations vidéo
Ces quatre petites vidéos 161eForth se poursuivent. La première vidéo au début de l'article.
Partie 2 sur 5. Tests TEST-TEST4 du livre "eForth and Zen", 3ème édition, sur le MK-161.
Partie 3 sur 5. VOIR le décompilateur.
Partie 4 de 5. Breakpoint BYE, terminal RS-232 et accès à distance au MK-161.
Partie 5 de 5. Mots finaux.