Section courante

A propos

Section administrative du site

Programmes - analyse, mots clefs et jetons

Un programme est entreposé, physiquement, sous forme de fichier. Logiquement, il est organisé comme ce qu'on appelle traditionnellement un fichier séquentiel. C'est-à-dire un fichier d'enregistrements (lignes) de longueurs variables, un enregistrement suivant l'autre, séquencé dans l'ordre 1-2-3.

Si vous enregistrez un programme sous forme de fichier ASCII (SAVE "programme", A), il est en fait sorti selon les conventions désormais connues sous le nom de «... fichier séquentiel standard».

Chaque ligne de votre programme est un enregistrement de longueur variable. Les deux derniers octets de chaque enregistrement sont une paire CR/LF (un retour chariot et un saut de ligne). La fin du fichier est marquée par un seul octet (code de Ctrl+Z) immédiatement après le dernier enregistrement. Tous les octets, dans tous les enregistrements, sont des codes de caractères ASCII standard. (Sauf ceux au-dessus de CHR$(127), n'étant pas vraiment ASCII.)

Et à un moment donné, la plupart des programmeurs novices écrivent des programmes expérimentaux pour "lire" les fichiers de programme. Certains passent rapidement à l'étape suivante et écrivent des programmes "écrivant" des programmes.

Les générateurs de programmes, en tant que concept, sont aussi anciens que l'activité de programmation elle-même. La première fois qu'un programmeur très expérimenté doit écrire quelques centaines de lignes se ressemblant beaucoup, il est très probable qu'il écrive un "outil" pour générer ces lignes automatiquement.

Au moment où la plupart des étudiants sont arrivés aussi loin, ils commencent également à souhaiter avoir plus d'outils. Et les vétérans d'autres langages de programmation remarquent très rapidement l'absence flagrante d'outils dans cet environnement.

Cette page cherche à combler un autre vide. Lorsque votre monde dicte le besoin d'outils sur mesure, devant fonctionner sur des programmes tels qu'ils sont en mémoire, ou tels qu'ils sont dans des fichiers ayant été enregistrés en tant que "binaires", ce qui se trouve dans ces octets doit être connu. Ce détail minutieux est fourni ici, mais pas seulement pour le bénéfice des rédacteurs d'outils.

Souffrez que mon affirmation préférée se répète souvent ailleurs : pour pouvoir écrire des programmes s'exécutant aussi efficacement que possible, il faut comprendre le fonctionnement de l'interpréteur. Cette page peut être lu pour approfondir cette idée, en savourant les concepts généraux, en sautant rapidement le cartilage.

Un bref préambule est nécessaire avant d'entrer dans le vif du sujet. Plus une note technique est explicite, plus elle est susceptible de se tromper. Pas à cause d'erreurs (étant certainement possibles), mais plus probablement parce que nous ne voyons pas exactement la même chose. Le monde change constamment autour de nous, et ce cliché est tellement applicable au monde de la programmation. Au cas où vous rencontreriez un octet tordu dans ce qui suit, percevez-le comme un simple caillou dans un ruisseau rapide : pataugez.

Un programme est entreposé, physiquement, sous forme de fichier. Logiquement, il est organisé comme ce qu'on appelle traditionnellement un fichier séquentiel. C'est-à-dire un fichier d'enregistrements (lignes) de longueurs variables, un enregistrement suivant l'autre, séquencé dans l'ordre 1-2-3. Cette répétition est toujours fondamentalement vraie, mais à partir de maintenant, lorsque vous enregistrez un programme sans l'option A-pour-ASCII, c'est un tout nouveau jeu de balle.

Un fichier de programme est, essentiellement, ce que l'on appelle parfois un vidage de mémoire d'image miroir sur le disque. C'est pourquoi l'activité de type LOAD et SAVE est rapide : La lecture et l'écriture se font sur la base de blocs physiques, et non au niveau de la ligne logique, ou de l'enregistrement. En mémoire (et donc sur disque), un programme est toujours organisé en interne sous forme de lignes discrètes, disposées par ordre de numéro de ligne, comme vous les voyez avec LIST ou LLIST.

Certes, cela peut être appris par une lecture attentive de la plupart des manuels. Certains mentionnent que les lignes sont entreposées sous une forme compacte, compressée ou en jeton. Ce qui est à peu près aussi loin que n'importe lequel d'entre eux va. Incontestablement, le programme d'interprétation est un logiciel spécial très sophistiqué, très compliqué. Mais cela reste un programme. Il "traite" votre programme. Cela commence là où vous le faites, sur la première ligne, en examinant chacune de vos déclarations, en faisant ce que vous lui dites de faire, une étape à la fois.

Cette définition grossièrement sous-estimée et trop simplifiée de l'interprète est la perspective fondamentale à partir de laquelle lire ce qui suit. Le but est de voir ce qui se trouve dans les lignes de programme elles-mêmes. Voyant cela, nous pouvons souvent deviner ce que l'interprète doit faire. Comment il le fait réellement peut rester obscur.

Toutes les lignes commencent par les quatre premiers octets ayant le même ordre et le même objectif, et se terminent par un octet égal à CHR$(0). Les deux premiers octets sont une paire d'adresses. Ils contiennent l'adresse réelle du début de la ligne suivante. En commençant par les deux octets suivants, la paire contenant votre numéro de ligne, tout ce qui se trouve dans une ligne est exactement dans le même ordre que lorsqu'elle est vue comme une ligne de texte ASCII. Là s'arrête sa similitude. Les bits dans les octets eux-mêmes sont formulés pour convenir à l'interpréteur.

Certains octets coïncident toujours avec l'ensemble de caractères ASCII et leur interprétation reste inchangée. Étant donné que n'importe quel octet donné peut s'étendre sur le spectre complet de 8 bits de 0 à 255, en nombres décimaux, la plupart d'entre eux ressembleront forcément à des caractères affichables. Mais un octet ressemblant à un CHR$(65) peut ne pas être du tout pour la lettre "A". Il peut s'agir d'un code, ou d'une partie d'un code, ou d'un nombre, ou d'une partie d'un nombre, ou...

Les octets d'une ligne sont analysés comme des codes à 1 octet ou comme des mots (groupes d'octets). Un mot peut être aussi petit que 1 octet. Certains sont 2, d'autres 4, et naturellement, certains sont 8. Saisissez maintenant ce fil qui est tissé tout au long de la programmation en langage machine : des octets de 8 bits utilisés comme mots de 1, 2, 4 ou 8 octets.

Presque tous les soi-disant "mots clefs" en BASIC sont entreposés sous forme de jetons (codes). Lorsque vous tapez une ligne d'un programme à l'aide de l'éditeur BASIC, le texte de ce que vous tapez est traduit. Le mot clef BEEP est entreposé sur un seul octet, par exemple ; il ressemble à un CHR$(197). Lorsque vous voyez BEEP, un jeton égal au nombre 197, en décimal, a été retraduit dans les quatre lettres ASCII majuscules épelant BEEP.

À partir de maintenant, supposons que tous mes nombres sont décimaux. Continuer à utiliser des phrases pour s'assurer que 197 est compris comme signifiant un octet équivalent à CHR$(197) est redondant. Cela ralentit votre lecture, et mon écriture.

De nombreux jetons de mots clefs sont, en fait, des codes à deux octets. Le premier octet sert d'indicateur que le jeton dans l'octet suivant provient d'une autre table de traduction. Le jeton pour SWAP est 164 et le jeton pour LOC est également 164. Ainsi, un octet de jeton de 164 est soit pour SWAP, soit pour LOC, selon la table utilisée pour la traduction, c'est-à-dire si le jeton est précédé ou non d'un octet indicateur d'une table de 255.

En tout, il y a quatre tableaux de mots clefs. Le jeton de 129 octets unique se traduit par END. Un 255 octets suivi de 129 est traduit par LEFT$, un 254 puis un 129 est pour FILES, et 253 suivi de 129 signifie CVI.

Étant donné que le premier octet dicte comment le jeton le suivant doit être traduit, nous pouvons obtenir un aperçu immédiat du fonctionnement réel de l'interpréteur. Il traite une ligne de gauche à droite, un octet à la fois. Sur la base de ce qu'un octet contient, il peut procéder au rythme d'un octet à la fois ou engloutir 2, 4 ou 8 octets pour son tour suivant.

Lorsqu'un programme est "en cours d'exécution", lorsque l'interpréteur tombe sur un 253 octets, par exemple, il sait que l'octet suivant est un jeton, et ce sera un appel de fonction pour faire CVI, CVS, CVD, MKI$, MKS$, MKD$ ou EXTERR (car seuls 7 jetons uniques doivent suivre un octet qui en contient 253).

Remarquez comment "un octet" indique ce qui devrait être attendu ensuite. Être capable d'analyser une ligne - pour la séparer en mots d'unités lexicales) - nécessite simplement un algorithme imitant la logique de la façon dont l'interprète le fait. Et ce n'est pas très compliqué du tout.

Construire un outil traduisant le nombre 145 dans le mot PRINT, par exemple, ne demande pas beaucoup d'efforts. Ce qu'il faut en termes de routines pour exécuter une commande telle que PRINT peut prendre plusieurs centaines de lignes de programme. Sans voir ces lignes, ni même connaître les langages machine, nous pouvons apprécier les longues heures et le travail acharné ayant été consacrés à l'écriture de l'interprète lui-même. En parcourant une ligne, un octet à la fois, tout comme ce programme le fait, nous pouvons cependant saisir les principes de base selon lesquels il fonctionne. Comme ça :

Commencez au début : La première ligne de votre programme. Les deux premiers octets sont une paire d'adresses. Pour obtenir leur valeur décimale, le cas échéant, multipliez le deuxième octet par 256 et ajoutez à cela la valeur du premier octet. Et prenez note. Ce même exploit arithmétique peut être utilisé pour convertir tous les mots de 2 octets représentant des adresses ou des numéros de ligne. (Qui sont entreposés dans le fonctionnement du langage machine, c'est-à-dire à l'envers par rapport à la façon dont nous le ferions dans notre tête.)

Ajoutez 2 à votre pointeur d'octet. La prochaine paire d'octets est également un mot de 2 octets. Faites le calcul. Et voilà, le résultat est égal au numéro de ligne que vous avez utilisé lors de la création de cette ligne de programme. Maintenant, incrémentez votre pointeur d'octet de un et préparez-vous à vous amuser vraiment.

Si l'octet suivant est 32, 44 ou 58, il s'agit d'un espace, d'une virgule ou de deux-points, comme en ASCII. Si l'octet suivant est zéro, vous avez atteint la fin de la ligne. S'il est supérieur à 128, il s'agit d'un jeton de mot clef. Si aucun de ces tests n'est vrai, vous regardez maintenant quelque chose que vous avez inventé - un littéral, une constante ou un nom de variable - ou votre pointeur est au mauvais endroit. Ou vous essayez de lire le courrier de quelqu'un d'autre.

À ce stade, si vous écrivez réellement un outil de programmation, ce que vous voulez voir le plus, ce sont les tableaux à la fin de cette page. Mais ne commencez pas encore à coder. Il serait utile de savoir comment les informations contenues dans ces tableaux ont été compilées. (Au cas où votre version de l'interprète diffère de la mienne.) Et, il y a quelques bribes devant être connues qui ne sont pas évidentes en regardant uniquement les graphiques.

Essayez LCOPY = 1 et vous obtiendrez une erreur de syntaxe. LCOPY 0, en revanche, ne génère aucune erreur, mais ne fait rien non plus. LCOPY est une commande absente. Cela n'a fonctionné que dans une seule version, mais cela fonctionne maintenant simplement comme un Pas d'opération.

Pour savoir exactement quel jeton est utilisé pour représenter un mot clef donné, tapez-le comme premier mot dans un programme BASIC. Enregistrez-le, puis utilisez DEBUG - ou un autre outil - pour voir exactement en quoi l'interpréteur a converti ce mot. Soit dit en passant, le tout premier octet d'un fichier programme sauvegardé est un indicateur de type de fichier. (Il peut s'agir de 255, ce qui indique un programme BASIC "normal" ; 254 indique qu'il a été enregistré avec l'option "protéger".) N'oubliez pas également de sauter les quatre premiers octets au début de chaque ligne avant de commencer à chercher un jeton de mot clef.

Un premier octet de 254 ou 255 ne signifie pas toujours que ce qui suit est un programme BASIC ; c'est simplement ce que l'interpréteur recherche pour "savoir" si le fichier que vous chargez est un programme BASIC en jeton.

Si vous ne connaissez pas tous les mots clefs intégrés à votre version de l'interpréteur, il existe un moyen de le savoir. Mais ce n'est pas particulièrement facile. Malheureusement, ils ne sont pas tous indiqués dans tous les manuels, et certains, bien que contenus dans un manuel, peuvent ne pas figurer dans votre logiciel. Retournons à DEBUG. Videz l'interpréteur lui-même. Recherchez ce qui ressemble aux mots réservés BASIC. Ils ne sont pas entreposés en ASCII pur ; la première lettre d'un mot et la dernière lettre, ou les deux, peuvent ressembler à du charabia, mais les lettres au milieu des plus longues comme RANDOMIZE sont toujours reconnaissables comme des lettres majuscules ASCII.

Plus que de simples tableaux précis de mots clefs et de leurs jetons sont nécessaires. Voici quelques autres choses intéressantes à attendre lors de l'analyse des lignes BASIC. Et quelques informations supplémentaires sur le fonctionnement de l'interpréteur lorsqu'il exécute un programme.

Les littéraux numériques sont entreposés sur une ligne dans exactement le même format que si vous les aviez affectés à la variable la moins précise étant nécessaire pour les contenir. Par exemple : -32000 est entreposé sur deux octets (exactement comme dans une variable entière). Ce littéral en ligne est précédé d'un code - 28 indiquant que ce qui suit est un mot de 2 octets et qu'il doit être traduit par un entier. Voyez maintenant pourquoi il arrive que, bien que vous ayez tapé A=99999, plus tard vous verrez A=99999 ! quand vous faites une LIST. (Les nombres entiers n'obtiennent pas d'un index libre, mais tous les nombres plus grands en ont, ou ils sont lus comme si vous les aviez tapés en utilisant une notation pseudo-scientifique.)

Ce même concept est vrai pour toutes les valeurs en ligne. Ils sont entreposés dans un format prêt à l'emploi. Aucune conversion n'est nécessaire. L'interprète peut saisir un mot de 1, 2, 4 ou 8 octets et l'utiliser instantanément, tel quel. Il est préférable de faire la conversion pendant que vous tapez. Vous ne saurez même pas quand ce sera fait. (Peu de dactylographes peuvent dépasser un micro moderne.) Voyez aussi pourquoi une MERGE peut prendre un certain temps : il y a beaucoup de conversions en cours pendant le processus de chargement.

Il existe un type de conversion ayant lieu pendant l'exécution d'un programme. Si vous fouillez dans la mémoire des programmes pendant qu'un programme est en cours, faites attention à celui-ci.

GOTO, par exemple, est suivi d'un numéro de ligne. Les numéros de ligne sont entreposés dans des mots de 2 octets. Ils sont normalement précédés d'un octet code - 14. Lorsque l'interprète tombe sur le 14, il parcourt votre programme pour trouver la ligne ayant le numéro de ligne correspondant. Maintenant, la partie délicate : les trois octets après le GOTO sont modifiés. Le code passera de 14 à 13 et l'adresse réelle de la ligne cible écrasera les deux octets de numéro de ligne.

La conversion des adresses traduites en numéros de ligne peut être effectuée très rapidement, soit dit en passant. Si vous tombez sur un code - 13, utilisez l'adresse le suivant pour obtenir la paire d'octets inchangée depuis le début (+2) de la ligne cible et modifiez l'octet de tête de 13 à 14.

La plupart du temps, vos variables ressemblent à celles que vous avez saisies. Sous forme de lettres majuscules ASCII, de chiffres et d'index. Une exception est le cas d'un nom de fonction défini par l'utilisateur. Le FN lui-même est converti en un jeton de 1 octet (209), mais le reste de votre nom reste inchangé.

Une confusion - et pas une petite aggravation - peut survenir lorsque vous analysez uniquement des variables. Tous les mots clefs ne sont pas des jetons. Il n'y en a que quelques-uns qui ne le sont pas, mais parce qu'ils sont entreposés en interne sous forme de lettres ASCII, ils doivent être analysés comme s'ils étaient des variables. Ensuite, vous pouvez décider si vous avez inventé le nom ou BASIC. Ceux étant et ceux n'étant pas des mots clefs ont tendance à être parfois différents. (Si vous appelez votre machine PC Junior, faites attention à PALETTE. Les seniors utilisent un jeton, mais certains PC Jr ne le font pas.)

Autre perversité : B et BF peuvent certainement être des noms de variables. Mais il peut aussi s'agir de "mots clefs sans jetons". S'ils suivent la deuxième virgule dans une instruction graphique LINE, ce sont simplement des commutateurs pour conditionner la façon dont cette instruction est exécutée. Pour trouver toutes les variables, uniquement, avec précision, votre algorithme devra devenir sensible au contexte lorsqu'il rencontre le jeton 176 pour LINE. Un jeton 133 peu de temps après signifie que vous avez trouvé LINE INPUT et tout B ou BF ultérieur sont des variables. Sinon, les lettres B ou BF - après une virgule de deux - peuvent être ignorées.

Les instructions DATA sont toujours des lignes entières. Si le premier jeton suivant un numéro de ligne est 132, l'octet suivant doit être 32 (un espace) et le reste de la ligne est en ASCII pur jusqu'au dernier octet (qui est toujours zéro). Notez également que les éléments DATA numériques ne sont convertis au format interne qu'au moment où vous effectuez une lecture. Un autre indice de performance, quoique plutôt petit. (La lecture de chaînes de caractères de littéraux à partir d'instructions DATA n'est pas un moyen efficace de programmer.)

Les déclarations de remarque sont intéressantes et un peu étranges. Un jeton de 143 se traduit par REM, mais seulement si l'octet suivant n'est pas 217. Les deux d'affilée - 143 et 217 - se traduisent par une apostrophe, le symbole abrégé d'une remarque. (Et cette paire est suivie d'un code - 58 imbriqué arbitrairement - deux-points - pour une raison obscure.) Au-delà de cela, tout ce que vous avez tapé est entreposé tel quel, sous forme de caractères ASCII. Notez également que la remarque la plus courte est d'au moins deux octets. Si vous utilisez REM, il est entreposé sous la forme 143 suivi du caractère d'espace syntaxiquement requis (32). Deux octets. Si vous utilisez l'apostrophe, elle est entreposée sous la forme 143, puis 217, puis 58, mais aucun espace n'est requis. Trois octets. Ainsi, REM est moins coûteux que l'apostrophe (mais est moins agréable visuellement).

Autre remarque sur les performances : les instructions DATA et les remarques sont, en fait, des octets ne faisant rien lorsqu'elles sont rencontrées par l'interpréteur pendant qu'il exécute un programme. Pour passer du jeton au début de la ligne suivante, l'interpréteur doit avancer, un octet à la fois, tout en cherchant le zéro à la fin. (Il a apparemment oublié quelle adresse se trouve dans la paire d'octets au début de cette ligne.) Donc, utilisez les remarques librement, mais ne les placez qu'après des déclarations ayant une conclusion emphatique. Après NEXT au lieu de après FOR, par exemple. Et n'intercalez jamais d'instructions DATA dans un flux de lignes exécutables, sauf si vous aimez les programmes s'exécutant plus lentement que nécessaire.

Bien que le jeton pour ELSE (161) provienne de la table des jetons à un octet, il est toujours précédé d'un 58, étant normalement considéré comme un séparateur d'instructions. Ainsi, lorsque vous tombez sur un 58, regardez l'octet suivant avant de supposer que ce qui s'en vient est la prochaine déclaration sur une ligne multi-instructions. (Normalement, ELSE ne devrait venir qu'après THEN, comme nous le savons tous.)

Les guillemets sont également un peu étranges. Ils sont entreposés sous forme de 34, comme en ASCII, mais ils sont censés être utilisés par paires. Si, par exemple, PRINT "bonjour" est rencontré, le premier guillemet désactive la segmentation. Le suivant le rallume. Ainsi, tout ce que vous mettez entre guillemets est entreposé tel que vous l'avez tapé. Et si vous n'en tapez pas un deuxième, tout, depuis le premier guillemet jusqu'à la fin de la ligne, est traité comme une chaîne de caractères de texte continue. Ce qui explique pourquoi vous voyez parfois des trucs marrants. (Une citation manquante peut être la cause de certains bogues pas si drôles.)

Les parenthèses, en revanche, doivent être utilisées dans des paires correspondantes, et elles sont entreposées respectivement sous les codes 40 et 41. Ou vous déclencherez une trappe d'erreur. Le jeton LEFT$, par exemple, devrait toujours être immédiatement suivi d'un octet code - 40.

Un autre aparté : découvrez ci-dessus pourquoi un piège à erreur peut parfois prêter à confusion. Vous l'avez confondu. Les parenthèses et autres "caractères de syntaxe" sont fondamentaux pour l'analyse d'une ligne. Certains codes indiquent que le pointeur d'octet doit avancer d'un nombre spécifique d'octets. Si le code trouvé à ce moment-là n'est pas ce qui est normalement attendu, on peut supposer que celui ayant tapé cette ligne ne respectait pas les règles. La meilleure "erreur" pouvant être donnée est basée sur ce que le pointeur voit maintenant. Les octets écrasés font partie de l'historique.

Et certains octets devraient être historiques. Les octets étant vraiment des bosses ne sont pas différents des dos d'âne dans les stationnements. Ils ralentissent votre programme. Pas toujours beaucoup, peut-être, mais si vous aimez les programmes s'exécutant dans la voie rapide, omettez tout ce qui est "facultatif". Plusieurs fois, le troisième paramètre des expressions MID$ peut être omis. Le signe dièse peut presque toujours être omis. Il est obligatoire avant le numéro de fichier dans les instructions INPUT, PRINT et WRITE. Mais les règles sont incohérentes lorsqu'un numéro de dossier est utilisé entre parenthèses. Comme dans VARPTR(#1), la règle est différente de celle de LOF(1). Ce qui n'est pas la seule incohérence concernant les parenthèses.

Pour une raison étrange, la parenthèse gauche n'est pas entreposée dans une ligne dans deux cas. Les mots clefs TAB et SPC ont leur index final intégré dans les tables de traduction. Leurs jetons ne seront pas suivis d'un code de 40. Et ces deux sont pervers d'une autre manière : ils ne peuvent être utilisés que sous une certaine forme d'instruction PRINT. Vraisemblablement, ces traits génétiques ont quelque chose à voir avec leur héritage.

Un certain nombre de caractéristiques familiales sont perceptibles dans les tableaux de traduction des mots clefs. La plupart de ceux de la première famille sont des commandes (par opposition aux fonctions). On ne s'attend pas à ce que la plupart de ces enfants aient des expressions entre parenthèses derrière eux. Les jetons de cette famille vont de 129 à 244, avec quelques lacunes. Certaines des lacunes sont causées par la mortalité infantile - des mots clefs figurant autrefois dans BASIC mais n'étant plus avec nous. Et certains sont des adoptions récentes, des mots comme COLOR, ayant été ajoutés au fur et à mesure que le langage de programmation s'est développée au fil des ans.

La deuxième famille est un peu plus pure race. C'est le gang gardé par un 255 octets. Tous ces mots clefs sont toujours suivis d'une parenthèse gauche, sauf le mot PEN. (Un cousin inadapté, sans aucun doute. Selon la façon dont il est utilisé, PEN peut ou non avoir un code de 40 octets derrière lui.) Les 37 enfants de ce clan sont numérotés de 129 à 165, et aucun ne manque. Ce qui implique, en l'absence de planification familiale, jusqu'à quatre-vingt-dix autres (166 à 255) pourraient apparaître dans une génération future de la langue.

La famille suivante sur la ligne, gardée par un 254 octets, ressemble à un orphelinat. Ce groupe de 27 jetons va de 129 à 155, sans lacunes. La plupart de ce groupe sont des nouveaux arrivants relatifs; en particulier ceux fournissant une interface avec le système d'exploitation. Pourtant, les plus anciens en haut de la liste existent depuis les versions juvéniles de Disk BASIC. Pendant longtemps, il n'y avait que six membres dans la quatrième famille, celle gardée par un 253 octets. Ces trois ensembles de jumeaux ont été conçus à l'origine pour être utiles pour travailler avec ce que l'on appelle des variables sur le terrain. (Cependant, ils ne sont pas limités à ce terrain de jeu.) Puis vint EXTERR. Remarquez les jetons vides.

Si cette page avait commencé par WHILE, nous sommes maintenant presque prêts pour WEND et une chute vers ces tables de fin. Vous souvenez-vous de ces deux octets au début de chaque ligne adressant le début de la ligne logique suivante ? Cette adresse n'est exacte que lorsqu'un programme réside en mémoire. Lorsque vous enregistrez un programme, ces adresses sont enregistrées, ainsi que tout le reste. Lorsque vous chargez, cependant, l'endroit où le fichier est placé en mémoire à ce moment-là peut être différent de ce qu'il était la dernière fois qu'il a été utilisé. Lors d'un LOAD (ou d'un RUN, ou d'un CHAIN), l'interpréteur doit recalculer toutes ces adresses.

Notez que les valeurs d'adresse sont proportionnellement correctes dans les fichiers de programme entreposés sur le disque. Un seul facteur d'addition ou de soustraction peut être appliqué à tous, pour maintenir leur relation en chaîne de caractères. De même, la différence des entêtes d'adresse de deux lignes successives peut être utilisée comme compte d'octets de la longueur d'une ligne.

Si vous lisez un programme tel qu'il se trouve dans un fichier, les adresses de ligne affichées sont celles étant, il était une fois. Si vous regardez un programme en mémoire, vous voyez les choses telles qu'elles sont maintenant. Quoi qu'il en soit, nous savons maintenant comment voir un programme tel que l'interprète le voit. Même si cette vision est encore un peu floue, cet oubli élargira, espérons-le, l'horizon.

Affectations de code interne

Valeur Description
0 Fin d'une ligne de programme
1 à 10 Non utilisé (ne devrait pas être rencontré)
11 Traduire les 2 octets suivants en Octal, comme &O1024
12 Traduisez les 2 octets suivants en hexadécimal, comme &H7D0B
13 Les 2 octets suivants sont l'adresse d'une autre ligne
14 Traduire les 2 octets suivants en numéro de ligne.
15 Traduire l'octet suivant en un littéral numérique (0 à 255)
16 Non utilisé (ne devrait pas être rencontré)
17 à 26 Traduire cet octet en chiffre décimal (0 à 9)
27 Marque la fin du fichier (précédé d'un octet zéro)
28 Traduire les 2 octets suivants en entier
29 Traduire les 4 octets suivants en un nombre simple précision
30 Non utilisé (ne devrait pas être rencontré)
31 Traduire les 8 octets suivants en nombre double précision
32 à 127 Traduire en tant que caractères de texte ASCII standard à moins que 58 est suivi de 161 ; traduire cette paire par ELSE
128 Non utilisé (ne devrait pas être rencontré)
129 à 252 Traduire comme un mot clef du tableau 1
253 Traduire l'octet suivant en mot clef du tableau 4
254 Traduire l'octet suivant en mot clef du tableau 3. Si le 1er octet du fichier, il a été enregistré avec l'option P
255 Traduire l'octet suivant en mot clef du tableau 2. Si le 1er octet du fichier, il s'agit d'un programme LOAD et aller à.

Tableau 1 = Jetons à un octet

Valeur Description
129 END
130 FOR
131 NEXT
132 DATA
133 INPUT
134 DIM
135 READ
136 LET
137 GOTO
138 RUN
139 IF
140 RESTORE
141 GOSUB
142 RETURN
143 REM
144 STOP
145 PRINT
146 CLEAR
147 LIST
148 NEW
149 ON
150 WAIT
151 DEF
152 POKE
153 CONT
156 OUT
157 LPRINT
158 LLIST
160 WIDTH
161 ELSE
162 TRON
163 TROFF
164 SWAP
165 ERASE
166 EDIT
167 ERROR
168 RESUME
169 DELETE
170 AUTO
171 RENUM
172 DEFSTR
173 DEFINT
174 DEFSNG
175 DEFDBL
176 LINE
177 WHILE
178 WEND
179 CALL
183 WRITE
184 OPTION
185 RANDOMIZE
186 OPEN
187 CLOSE
188 LOAD
189 MERGE
190 SAVE
191 COLOR
192 CLS
193 MOTOR
194 BSAVE
195 BLOAD
196 SOUND
197 BEEP
198 PSET
199 PRESET
200 SCREEN
201 KEY
202 LOCATE
204 TO
205 THEN
206 TAB(
207 STEP
208 USR
209 FN
210 SPC(
211 NOT
212 ERL
213 ERR
214 STRING$
215 USING
216 INSTR
217 ' (rem)
218 VARPTR
219 CSRLIN
220 POINT
221 OFF
222 INKEY$
(lacunes: 154, 155, 159, 180 à 182, 203, 223-229, 245 à 255)
230 >
231 =
232 <
233 +
234 -
235 *
236 /
237 ^
238 AND
239 OR
240 XOR
241 EQV
242 IMP
243 MOD
244 \

Tableau 2 = Jetons de mots clefs précédés de 255

Valeur Description
129 LEFT$
130 RIGHT$
131 MID$
132 SGN
133 INT
134 ABS
135 SQR
136 RND
137 SIN
138 LOG
139 EXP
140 COS
141 TAN
142 ATN
143 FRE
144 INP
145 POS
146 LEN
147 STR$
148 VAL
149 ASC
150 CHR$
151 PEEK
152 SPACE$
153 OCT$
154 HEX$
155 LPOS
156 CINT
157 CSNG
158 CDBL
159 FIX
160 PEN
161 STICK
162 STRIG
163 EOF
164 LOC
165 LOF

Tableau 3 = Jetons de mots clefs précédés de 254

Valeur Description
129 FILES
130 FIELD
131 SYSTEM
132 NAME
133 LSET
134 RSET
135 KILL
136 PUT
137 GET
138 RESET
139 COMMON
140 CHAIN
141 DATE$
142 TIME$
143 PAINT
144 COM
145 CIRCLE
146 DRAW
147 PLAY
148 TIMER
149 ERDEV
150 IOCTL
151 CHDIR
152 MKDIR
153 RMDIR
154 SHELL
155 ENVIRON
156 VIEW
157 WINDOW
158 PMAP
159 PALETTE
160 LCOPY
161 CALLS
162 ---
163 ---
164 ---
165 PCOPY
166 ---
167 LOCK
168 UNLOCK

Tableau 4 = Jetons de mots clefs précédés de 253

Valeur Description
129 CVI
130 CVS
131 CVD
132 MKI$
133 MKS$
134 MKD$
135 ---
136 ---
137 ---
138 ---
139 EXTERR

Mots clefs sans jeton (conservés en ASCII)

Mots clefs Description
ACCESS comme dans OPEN ... FOR RANDOM ACCESS
AS comme dans OPEN ... AS --- et --- FIELD ... AS
ALL comme dans CHAIN ... ,ALL
APPEND comme dans OPEN ... FOR APPEND
BASE comme dans OPTION BASE 0 --- ou --- OPTION BASE 1
OUTPUT comme dans OPEN ... FOR OUTPUT
RANDOM comme dans OPEN ... FOR RANDOM
SHARED comme dans OPEN ... SHARED
SEG comme dans DEF SEG

Code source

Voici des exemples de code source de manipulant les jetons :

Lien Langage de programmation Projet
https://github.com/gladir/corail/blob/master/CAT.PAS Free Pascal/Turbo Pascal Corail
https://github.com/gladir/corail/blob/master/TOKEN2BAS.PAS Free Pascal/Turbo Pascal Corail
https://github.com/gladir/corail/blob/master/TYPE.PAS Free Pascal/Turbo Pascal Corail
https://github.com/gladir/corail/blob/master/VIEWBAS.PAS Free Pascal/Turbo Pascal Corail


Dernière mise à jour : Dimanche, le 19 mars 2023