Introduction
Téléchargement
Spécificité
Installation
Aide Dos
Les langages
Mini-théorie
Responsabilité
Quelques mots
Entrainement 1
4 mot de vocabulaire
Mots de pile
Mots de pile 2
Lumière sur l'ordinateur
Boucle d'or
Les variables
Les constantes
Entrainement
2
SEE
Personnalisation
exercice
11
vocabulaire supp'
notions nouvelles
le code ASCII
|
Introduction
:
Ce petit tutoriel a pour objet une première introduction
au Forth. Il s'adresse au novice en matière d'informatique
et de programmation _Je suis moi même débutant_
Je poursuis deux buts en écrivant ce tutoriel :
-
Le premier très pretentieux: aider le novice
à approcher ce langage, et lui donner envie d'aller
voir plus profond.
Le second assurement atteint: bien faire rigoler ceux
qui s'y connaissent.
Quoi qu'il en soit je suis disponible (dans la maigre
mesure de mes connaissances) à répondre à
toutes les questions de ceux qui auraient des difficultés,
il suffit de me passer un courriel à:
jcboisserie@free.fr,
ou poser vos questions sur la liste de diffusion forth, pour
vous abonner :
forth-abonnement@club.voila.fr
|
Téléchargement
:
le plus simple est de lire le fichier telech.htm
sinon...
Le Forth utilisé pour les exemples est Turbo-Forth,
disponible gratuitement sur le site internet suivant:
ftp://ftp.acbm.com/pub/tforth/TF83.exe
ou sur:
http://www.acbm.com/magasin.html
Les deux manuels qui l'accompagnent dans sa version complète,
étaient disponibles auprès son auteur pour 100,00
F TTC
Si vous télécharger le fichier TF83.exe,
pour simplifier, nous considérerons que vous l'enregistrez
sur le A: (Ce qui indique qu'il faudra une disquette 1,44Mo
formatée dans le lecteur de disquette).
Je vous passerais toutes les manipulations sur le téléchargement
du fichiers.
Maintenant que vous avez enregistrer TF83.exe sur la disquette,
laisser la disquette dans le lecteur, il suffit de cliquer
sur Démarrer, puis clic
sur exécuter (une fenêtre
s'ouvre) tapez a:\forth83 clic
sur OK
Lors de l'installation des question
vous sont posée:
Voulez-vous extraire cette archive (oui/non) ? O
RÚpertoire de destination : [c:\tf83] si vous voulez le répertoire
dans c:\dudulle il suffit de tapez c:\dudulle
sinon, si le répertoir c:\tf83 vous convient taper
sur [entrée]
Le rÚpertoire c:\dudulle \tf83 n'existe pas. Faut-il le crÚer
? (oui/non) O
Un échantillon ci-dessous de se qui défilera
à l'écran.
faits : c:\dudulle \tf83 \EXEMPLES \MP \MP.DOC faits : c:\dudulle \tf83 \EXEMPLES \LIST \LIST.DOC
faits : c:\dudulle \tf83 \EXEMPLES \LIST \LIST.FTH faits : c:\dudulle \tf83 \EXEMPLES \ASTRING \ASTRING.FTH
faits : c:\dudulle \tf83 \lisezmoi.txt faits : c:\dudulle \tf83 \Update.txt
400 fichiers extraits contenant 2,668,909 octets.
Voilà pour l'installation
maintenant allez dans le répertoire de Forth est
double cliquer sur tfx386.exe pour en appréciez toute
la puissance et l'on se retrouve dans la leçon
suivante...
|
Spécificité
:
Turbo-Forth tourne sous le système d'exploitation
MS-DOS et avec les processeurs X86 d'intel, donc même
un vieux PC de 15 ans suffit, même si tout fonctionne
encore plus vite avec une machine plus récente.
|
Installation
:
Si vous avez la version disquette, la procèdure
à suivre est décrite ci-dessous ( elle
suppose que vous possédiez Windows 95 ou plus ). Si
vous n'avez que MS-DOS, vous n'aurez pas de mal a
adapter la méthode, si vous avez la version disponible
en téléchargement, je pense que vous pourrez
aussi vous débrouiller avec ce qui suit:
Pour commencer, il faut recopier la disquette sur le disque
dur : passer d'abord sous MS-DOS, une fois MS-DOS ouvert,
vous pouvez mettre la fenetre en plein écran en tapant
Alt-Entree, et la réduire ensuite de la même
façon. Après chaque ligne de commande, la frappe
de la touche entrée est symbolisée par le caractère
¬
Une fois sous DOS l'écran affiche ceci :
C:> C'est a dire "je suis sur le
disque C: dans le répertoire Windows et j'attends
des instructions". On va donc retourner au répertoire
racine C: en tapant :
cd.. ¬
l'écran affiche alors : C:>
On va créer un répertoire FORTH, et un sous-répertoire
TF83 en tapant les commandes suivantes :
md Forth ¬
cd Forth ¬
md TF83 ¬
cd TF83 ¬
l'écran affiche alors : C:>
On est alors dans le répertoire Forth, le sous répertoire
TF83. On va maintenant copier la diquette en tapant :
a: ¬
copy *.* c:¬
c: ¬
l'écran affiche alors :
C:>Forth>
On tape :
dir ¬
l'écran affiche la liste des fichiers présents
dans le répertoire. Maintenant on peut lancer TF83
en tapant :
TFX386 ¬
Pour les prochaines fois qu'on redemarrera, on se retrouvera
dans MS-DOS, avec l'affichage suivant :
C:>
Là il vous faudra taper :
cd.. ¬
cd forth ¬
cd tf83 ¬
tfx386 ¬
ou bien créer un ficher avec le programme Dos "EDIT"
qu'on lance sous dos en tapant :
edit ¬
dans lequel vous taperez les 4 lignes de commandes, et que
vous enregistrerez dans le répertoire Windows sous
le nom (par exemple) TF.BAT, ainsi lorsque vous serez avec
l'affichage :
C:>
Vous taperez simplement :
tf ¬
et Turbo-Forth 83 sera lancé.
|
Aide Dos :
il faut connaitre le fonctionnement de quelques commandes
DOS :
cd dudullle: Change Directory (changement
de répértoire) vers dudulle
cd..: ChangeDirectory vers répertoire
parent (remonte au repertoire précédent contenant
celui sur lequel on se trouve).
md: MakeDirectory dudulle (fabrique un
répertoire) nommé dudulle
copy duglu.txt c:\dudulle : copie duglu.txt
dans le répertoire dudulle (l'aide vous
sera utile pour cette fonction de DOS).
a: ou c: : change l'unité de stockage
dir : Directory affiche le contenu du répertoire
courant
dir/p : Directory avec Pause, idem ci-dessus,
mais affiche page à page, il faut taper sur espace
pour la page suivante.
Pour connaitre le fonctionnement d'une commande DOS, il
faut taper :
nom_commande /? ¬ exemple: dir/?
ceci marche pour toutes les versions de DOS, mais essayez
aussi la commande :
help ¬
Si vous avez la chance qu'elle fonctionne, vous pourrez
voir toutes les
commandes DOS disponibles.
|
Les langages de programmation
:
Il existe un seul langage de programmation compréhensible
par les ordinateurs, c'est le langage machine, constitué
uniquement de 1 et de 0 (en fait des tensions éléctriques
de +5V et 0V -voire moins dans les ordinateurs les plus modernes).
Un ensemble de 1 et de 0 peut représenter pour la machine
deux choses, soit une commande, soit des données à
traiter selon la commande. Les premiers ordinateurs étaient
programmés et utilisés à l'aide de
cartes perforées. Cela était trés compliqué
et trés lent, par exemple rentrer la valeur 25 demande
en langage machine d'écrire : 11001 , pour 345,
il faut écrire : 101011001, en fait on traduit de base
10 (décimale) en base 2 (binaire). Pour se simplifier
la tâche, les informaticiens ont écrit un programme
de traduction en langage machine que l'on appelle ASSEMBLEUR,
qui représente aujourd'hui le seul langage réellement
proche de la machine utilisée. L'ASSEMBLEUR utilise
une base numérique intermédiaire pour communiquer
avec la machine, c'est la base 16 (héxadécimale)
-nous verrons tout cela ultèrieurement-. Comme c'est
le langage le plus proche de celui de la machine, l'assembleur
est appellé langage de bas niveau. Cependant, l'utilisation
de l'assembleur reste assez fastidieuse, aussi les informaticiens
ont écrit des langages plus proches du langage humain
pour faciliter la programmation, ce sont les langages de haut
niveau : dont le BASIC,le C, le PASCAL, le FORTH, etc...
L'inconvénient des langages de haut niveau, c'est
qu'ils utilisent des "traducteurs", et que les
traducteurs ne font pas toujours les phrases les plus courtes
que l'on aurait pu faire pour se faire comprendre. Ce
qui fait qu'un programme écrit en langage de haut
niveau est toujours plus lent que le même programme
écrit en assembleur (sauf à le faire exprès).
C'est pour cela que l'assembleur est toujours utilisé.
Les langages de programmation de haut niveau se divisent en
deux groupes : les langages INTERPRÈTES (ex: Basic),
et les langages COMPILÉS (ex: C).Les langages compilés
sont traduits en entier une seule fois, et convertisen langage
machine et sauvegardés sous cette forme. Les langages
interprétés sont traduits au vol en langage
machine, et chaque ligne est traduite, puis exécutée,
avant de traiter la suivante. Les langages compilés
ont le défaut que l'on ne peut pas les exécuter
directement, et il faut recompiler à chaque modification
du programme, par contre, cela fait, ils sont d'une très
grande rapidité d'exécution. Les langages
interprétes sont exécutables directement, mais
sont en contrepartie beaucoup plus lents à l'exécution.
Le Forth est quand à lui un langage atypique , qui
est alternativement interprété et compilé,
et qui est aussi alternativement de haut et de bas niveau.
C'est un langage struturé (pas de GOTO), basé
sur l'utilisation d'une pile (comme les piles d'assiettes),
sa syntaxe utilise la notation polonaise inversée (comme
les calculatrices HP), et qui contient son propre assembleur.
|
Mini théorie
:
La mémoire des ordinateurs et les
ordinateurs eux même ne comprennent que les 1 et les
0. Ainsi, une position binaire (qui prend une valeur 1 ou
0) est appellée un bit; quatre positions binaires sont
appellées un quartet (ou nibble en anglais), huit positions
binaires sont appellées octet (ou byte en anglais -attention
aux confusions avec bit-), seize positions binaires sont appellées
mot (ou word en anglais), trente deux positions binaires sont
appellées mot-long (ou double-word en anglais). Ces
notions sont suffisantes pour débuter, mais très
importantes, résumons les en un tableau :
Nbre positions binaires
|
Appellation
|
Relations diverses
|
1
|
Bit |
|
4
|
Quartet (nibble) |
= 4 bits |
8
|
Octet (Byte) |
= 8 bits = 2 quartets |
16
|
Mot (Word) |
= 16 bits = 2 octets |
32
|
Mot-long (Double-word) |
= 32 bits = 4 octets |
|
Responsabilité
:
La version de Forth que nous allons utiliser
(Turbo Forth), est une version16 bits. Il est primordial de
bien comprendre que la machine n'est dotée d'aucune
intelligence, tout ce qu'elle sait faire, c'est manipuler
des 1 et des 0 très rapidement et en très grande
quantité, et seulement de la façon dont on le
lui a demandé de le faire. La machine ne fait pas d'erreurs,
ses concepteurs, ses programmeurs et ses utilisateurs
si. La machine ne réfléchit pas elle fait bêtement
sans comprendre et sans chercher à le faire (elle ne
peut pas). Ainsi si nous demandons a la machine d'additionner
2 et 3, celà ne signifiera rien pour elle, par contre
elle saura faire cette opération sur les 1 et 0 qui
représenteront ces deux nombres.
Revenons a notre langage Forth. La version est
16 bits, cela signifie que les élements de base manipulés
par TF ont une largeur de 16 bits qui peuvent prendre les
valeurs 1 ou 0, autrement dit les valeurs manipulées
par TF varieront entre 0000 0000 0000 0000 et 1111 1111 1111
1111 en binaire, soit pour faire plus court et plus compréhensible
pour nous entre 0 et 2^16 ( l' accent circonflexe
note l'opération exposant) soit 65536 en décimal.
Nous voyons donc que ce langage ne sait manipuler que des
entiers, et dans un intervale restreint. De plus, pour manipuler
les entiers négatifs, les valeurs de 32768 a 65536
représentent les entiers négatifs de -32768
à -1. Donc pour avoir des résultats cohérents
dans les opérations sous TF, il faut que le résultat
soit compris entre 0 et 32767 pour un résultat positif,
et entre -1 et -32768 pour un résultat négatif.
Il existe tout de même, une possibilité en utilisant
des opérateurs spéciaux de travailler sur des
nombres 32 bits, dont l'intervalle de valeurs varie de
0 a 2^32, soit de 0 à 4294967296, et qui permettent
de travailler sur les entiers entre -2147483648 et 2147483647.
Pour effectuer des calculs en virgule flottante, il existe
des extensions au langage de base, qui représentent
les nombres en deux parties, la mantisse et l'exposant,
ainsi, par exemple 2,75468 sera représenté par
la mantisse 275468 (entier) et l'exposant -5 (entier),
car 2,75468 = 275468*10^-5 (* est le signe de la multiplication),
évidement, cette représentation exige un programme
particulier pour effectuer les opérations, et les opérations
sont beaucoup plus lentes que sur des entiers. Ces considérations
sont importantes, car un obtient quelquefois des résultats
qui paraissent incohérents, à cause de ces limitations,
et il faut alors user d'astuce pour les contourner. Le
Forth est un langage qui utilise un vocabulaire (un ensemble
de mots qui ont chacun une fonction particulière),
et une syntaxe (quelques règles grammaticales). Le
vocabulaire de Forth peut être étendu, c'est
a dire qu'on peut lui apprendre des mots nouveaux, en
les définissants à partir des mots existants
(c'est d'ailleurs ainsi que l'on programme en
Forth). En ce qui concerne la syntaxe, il convient de noter
qu'un ou plusieurs espaces doivent séparer deux
mots, et que l'ordre des mots est primordial, le premier
mot rencontré est exécuté avant le second,
etc... Les mots Forth comprennent de 1 à 31 caractères
( ces caractères doivent avoir un code ASCCI compris
entre 1 et 127 - voir plus bas ), y compris les signes de
ponctuation et les chiffres, à l'exception de l'espace,
on pourrait ainsi définir le mot : C'est_la_mere_Michelle_qui_a_p
(c'est un peu long pour être pratique d'emploi,mais
c'est possible).
|
Quelques mots
:
Voici quelques mots
Forth, et leur action :
+
Addition
-
Soustraction
/
Division entière
*
Multiplication
.
Affichage destructif du sommet de la pile
.s
Affichage non destructif de la pile
Qu'est ce que c'est cette histoire de pile? Le Forth
est un langage à pile, c'est à dire qu'il
faut déposer sur une pile les données que l'on
veut faire traiter par Forth, et qu'il renvoie lui même
les résultats sur cette pile. Ainsi si je veux additionner
2 et 3, je dois les déposer sur la pile en tapant (les
commentaires sont entre parenthèses) :
2¬
( il y a 2 sur la pile )
3¬
( il y a 2 et 3 sur la pile, 3 au dessus de
2 )
+¬
( Forth utilise 2 et 3, et renvoie 5 sur la
pile )
.¬
( On affiche le résultat, et la pile
est a nouveau vide )
On aurait pu écrire la même phrase Forth comme
ceci :
2 3 + .¬
Notons que la multiplication et l'addition sont
commutatives, et que donc l'ordre des opérandes
est sans importance, ce qui n'est pas le cas pour la soustraction
ou la division, ainsi :
3 2 - .¬
(affichera 1)
2 3 - .¬
(affichera -1)
4 2 / .¬
(affichera 2)
2 4 / .¬
(affichera 0 -division entiere-)
L'état de la pile est très important, c'est
pourquoi, on représente souvent l'état de
la pile avant et après une opération par un
descripteur de pile noté entre parenthèses,
ainsi pour l'addition le descripteur est :
( n1 n2 -- n1+n2 ), c'est à dire on prend l'entier
n1 et l'entier n2 sur la pile, on fait l'opération
symbolisée par les deux tirets ( certains en utilisent
trois ), et la pile se retrouve avec un entier étant
la somme de n1 et n2 au sommet, on aurait aussi pu écrire
le descripteur de pile comme ceci ( n1 n2 -- n3 ), mais on
n'aurait moins de précision sur la valeur de n3.
Notons que dans le descripteur de pile, l'élément
le plus à droite (de part et d'autre des tirets)
représente le sommet de la pile. Si l'on veut exécuter
l'opération suivante : (1+2)*(5-1), comme Forth
ne connait pas les parenthèses pour les calculs, il
faudra écrire :
1 2 + 5 1 - * .¬
(déposer 1 et 2 les additionner-première
parenthèse- déposer 5 et 1 soustraire le second
du premier-deuxième parenthèse- multiplier et
afficher) Décomposons cette formule et affichons
l'état de la pile :
1 2¬ ( -- 1
2 )
+¬ (
1 2 -- 3 )
5 1¬ ( 3 --
3 5 1 )
-¬ (
3 5 1 -- 3 4 )
*¬ (
3 4 -- 12 )
¬ (
12 -- )
NB : Lorsque Forth attends des ordres, il affiche
OK.
|
ENTRAINEMENTS
:
taper dans TF :
HELP +¬
HELP -¬
HELP /¬
HELP *¬
HELP .¬
HELP .s¬
additionner 45 et 65
additionner 5200 et 35000
soustraire 56 et 14
multiplier 55 et 25
multiplier 1375 et 56
diviser 6 par 2
diviser 6 par 4
diviser 4 par 6
effectuer l'opération (15-2)/(5+2)
effectuer l'opération (15*3-5*3)/(12/5+13)
se familiariser avec tout ce bazar! poser des questions s'il
y en a (il faut bien saisir le fonctionnement de la pile,
et se remémorer qu'elle fonctionne exclusivement
en LIFO -dernier empilé, premier dépilé-).
Donc en cas de problème pour ces petits entrainements
: mèl !
|
4 mots de vocabulaire
:
Continuons par un peu de vocabulaire Forth supplémentaire,
ensuite, nous serons capables de créer des mots nouveaux.
Les mots nouveaux sont représentés en début de ligne sur les
lignes suivantes, avec leurs appellations entre parenthèses
:
: (deux points)
; (point-virgule)
( (parenthèse ouvrante)
) (parenthèse fermante)
Comme ces quatres mots font partie du vocabulaire Forth ils
ont les fonctions suivantes :
:
marque le début de la definition d'un nouveau mot Forth
; marque la fin d'un nouveau
mot Forth
(
marque le début d'un commentaire dans une définition
_les commentaires ne seront pas exécutés_. Notons qu'il faut
un espace entre les parenthèses et les mots qui les entourent,
comme d'ailleurs tous les autres mots Forth.
) marque la fin d'un
commentaire dans une définition.
(
et ) sont utilisés
en général pour inclure le descripteur de pile dans la définition
du nouveau mot. Par exemple, créons un mot qui additionne
les deux derniers éléments de la pile, et les multiplie par
l'avant-avant dernier, appellons ce mot ADDITION_MULTIPLICATION,
le descripteur de pile de ADDITION_MULTIPLICATION
sera donc : ( n1 n2 n3 -- (n2+n3)*n1
), ou bien ( n1 n2 n3 -- n4 )
qui serait moins explicite. Pour créer ADDITION_MULTIPLICATION,
nous taperons ceci :
: ADDITION_MULTIPLICATION + * ;
¬ ou bien :
: ADDITION_MULTIPLICATION ( n1 n2 n3
-- n4 ) + * ;¬
puisque les commentaires ne sont pas exécutés.
|
Mot de pile
:
Comme la pile est l'élément central
de Forth, il existe des mot spécifiques pour modifier le contenu
de la pile :
DUP
( n1 -- n1 n1 ),duplique le nombre
au sommet de la pile, et l'empile. ce mot est utile par exemple
pour définir un mot qui élèvera un nombre au carré (CARRE)
ou au cube (CUBE) :
: CARRE ( n1
-- n1^2 ) DUP * ;¬ |
CARRE
duplique l'élèment au sommet de la pile et en calcule
le produit |
tapons
:
2 CARRE .¬ |
l'affichage
donne 4 OK |
EXERCICE 1 :
écrire CUBE ( n1 -- n1^3 ) et l'essayer.
|
Mot de pile 2
:
DROP ( n1 -- ),
enlève le nombre au sommet de la pile.
SWAP ( n1 n2 --
n2 n1 ), échange l'ordre des deux valeurs au sommet
de la pile.
EXERCICE 2 : écrire OTEDE ( n1 n2 -- n2-n1 ) et l'essayer
(qui fasse par exemple 2 oté de 3)
OVER ( n1 n2 --
n1 n2 n1 ), duplique l'avant dernier élèment de la
pile et le dépose au sommet.
EXERCICE 3 : écrire CARREMUL ( n1 n2 -- n1^2*n2 ) et l'essayer
qui fasse par exemple 3^2*5
ROT ( n1 n2 n3 --
n2 n3 n1 ), effectue une rotation des trois derniers
élèments sur la pile. En fait enlève n1 de sa position et
le dépose au sommet.
-ROT ( n1 n2 n3
-- n3 n1 n2 ), effectue une rotation inverse des trois
derniers élèments sur la pile. En fait enlève n3 du sommet,
et l'insère avant n1.
PICK ( n(a) n(a+1)
... n(a+x) a -- n(a) n(a+1) ... n(a+x) n(a) ), empile
l'élèment situé au a-ième rang avant le sommet de la pile,
ainsi, si on a la pile de départ : 5 4 3 2 1 , et que l'on
fasse 3 PICK , on aura la pile d'arrivée : 5 4 3 2 1 4 , c'est
à dire que le nombre 3, que l'on empile avant le PICK, est
un paramètre consommé par PICK, et n'est pas compté, et que
de plus la numérotation des élèments sur la pile commence
au rang zéro pour le sommet de la pile. ( voir HELP PICK dans
TF83).
TUCK ( n1 n2 __
n2 n1 n2 ), recopie le sommet de la pile sous les deux
derniers élèments empilés.
ROLL ( n(a) n(a+1)
... n(a+x) a -- n(a+x) n(a) ... n(a+x-1) ), effectue
une rotation du a-ième élèment vers le sommet de la pile,
ainsi si on a la pile de départ : 5 4 3 2 1, et que l'on fasse
3 ROLL, on aura la pile d'arrivée : 5 3 2 1 4, c'est à dire
que le nombre 3 que l'on empile avant ROLL, est un paramètre
consommé par ROLL, et n'est pas compté, et que de plus la
numérotation des élèments sur la pile commence au rang zéro
pour le sommet de la pile. ( voir HELP ROLL dans TF83).
NIP ( n1 n2 -- n2
), enlève l'avant dernier élèment empilé. D'une manière
générale, il est toujours bon de faire HELP LE_MOT dans TF83
pour chaque mot dont je donne la définition ci-dessus. Et
il est toujours profitable d'empiler quatre ou cinq nombres
sur la pile, d'exècuter le mot nouveau défini, et de faire
.S pour bien visualiser son action
sur la pile. Voici ci-dessous quelques exercices de redéfinition
de mots de manipulation de la pile à l'aide d'autres mots
de manipulation de la pile. Ces nouvelles définitions sont
juste là pour apprendre a bien maitriser l'utilisation de
ces mots, il faut bien comprendre que ces mots prédéfinis
dans TF83, sont écrits en langage machine, et donc plus rapides
dans leurs versions originales : EXERCICE 4 : ecrire -ROTE
qui fasse exactement la même chose que -ROT,
avec un seul des mots définis ci-dessus ( utilisé deux fois,
genre : : -ROTE MOT MOT ; )
EXERCICE 5 : ecrire TUQUE qui fasse exatement la même chose
que TUCK, avec deux des mots que nous
connaissons déjà.
EXERCICE 6 : écrire NIPPE qui fasse exactement la même chose
que NIP à l'aide de deux mots que nous
connaissons déjà.
EXERCICE 7 : écrire SWAPE qui fasse exatement la même chose
que SWAP à l'aide d'un nombre et d'un
mot connu.
EXERCICE 8 : écrire OVEUR qui fasse exactement la même chose
qu'OVER à l'aide de mots connus.
EXERCICE 9 : écrire ROTE qui fasse exactement la même chose
que ROT à l'aide de... de de débrouillez-vous!
EXERCICE 10 : écrire DUPE qui fasse exactement la même chose
que DUP à l'aide de... de de débrouillez-vous!
|
Lumière sur l'ordinateur
:
Revenons à un peu d'architecture d'ordinateurs pour
nous changer les idées, et assimiler ce vocabulaire. On peut
comparer les ordinateurs a des machines à états successifs,
c'est a dire par exemple à l'éclairage d'une scène de théâtre.
On éclaire tantôt tel acteur, tantôt tel autre,
ou tel élément du décor, etc... Un ordinateur
fonctionne exactement de cette façon, mais avec des millions
de lampes ( chaque bit de la mémoire peut être assimilé
à une lampe ). Seulement, qui dit états successifs, sous-entend
temps, un temps pour l'état n, un temps pour l'état n+1. C'est
pourquoi tous les ordinateurs sont dotés d'une horloge qui
va battre la mesure des temps successifs. La conséquence
de cet état de faits, c'est qu'un ordinateur ne sait
pas faire plusieurs choses à la fois ( Lorsqu'on ouvre par
exemple plusieurs programmes sous Windows, on a l'impression
qu'ils s'exécutent en même temps, on dit en parallèle,
mais il s'agit juste d'une impression. En réalité les programmes
s'exécutent les uns après les autres petits bouts par
petits bouts, et on a l'illusion de la simultanéité.
), l'ordinateur fonctionne de manière séquentielle ( il exécute
une tâche, puis une autre, et encore une autre, etc... ).
Le fonctionnement séquentiel de l'ordinateur est primordial,
il permet de définir le programme, comme l'ensemble des tâches
successives effectuées par l'ordinateur. La programmation
consistant elle a définir les tâches que doit effectuer l'ordinateur
pour passer d'un état initial à un état final,
en fonction de certaines contraintes. Lorsque l'on a une tâche
a programmer, il y a quelques étapes clefs de la construction
du programme, certaines peuvent se confondre, mais elles ont
forcément fait partie du raisonnement qui conduit au
programme final : - définition des buts et des contraintes
- définition d'un algorithme (taches successives et points
clef du futur programme) - écriture du programme dans le langage
de programmation choisi - essais - corrections éventuelles.
|
Boucle d'or
:
Revenons un peu sur les algorithmes. Lorsque nous devons
faire une vérification du résultat d'une action précédente,
pour atteindre un certain but, on peut être amené a executer
cette action plusieures fois ( comme faire un pas pour aller
d'un point à un autre, il nous faut le refaire tant qu'on
n'est pas arrivés. )On appelle ces renvois en arrière dans
l'exècution des programmes des boucles, et chaque parcour
de la boucle est appellé itération. Il existe diffèrentes
sortes de boucles : Les boucles infinies qui ne se terminent
jamais, les boucles indéfinies dont on ne connait pas à l'avance
le nombre de fois que l'on va les parcourir et les boucles
définies, dont on sait avant d'entrer dedans que l'on va les
parcourir n fois. Les boucles et les conditions qui y font
entrer ou en sortir sont les élèments les plus importants
a maitriser en programmation. Il faut bien comprendre que
parce que ce sont des machines binaires, les ordinateurs ne
savent répondre que oui ou non ( 1 ou 0 ), et que si l'on
veut par exemple savoir si x est compris entre a et b ( a<x><b
) nous devrions tester si a><x, et si x>b, et seulement
lorsque ces deux conditions seront remplies, l'ordinateur
sera capable de dire a<x><b. une condition très
complexe peut toujours traduite plusieures conditions simples
( heureusement, sinon on ne pourrait pas faire grand chose
des ordinateurs), c'est la toute la difficulté de la programmation
( diviser en tâches et conditions de plus en plus simples
). Nous reviendrons sur les boucles un peu plus loin.
|
Les variables
:
Une autre notion capitale en informatique, maintenant :
les variables. Les variables, peuvent être considérées
comme des cellules mémoire d'emplacement fixe et définie,
et dont le contenu peut être appelé a évoluer
au cours de l'exécution d'un programme. Par exemple,
si je veux connaître les valeurs de x
qui résolvent l'équation ax+4=0,
pour a compris entre -5 et +5,
je peux définir une variable a qui contiendra successivement
le valeurs -5, -4, -3, -2, -1, 0, 1,
2, 3, 4, 5 à chaque parcours de la boucle (tiens
tiens) de résolution de l'équation. Les variables
servent aussi à 'passer' des données d'une partie
d'un programme à une autre. En Forth, les variables
sont aussi utilisées, mais beaucoup moins que dans
d'autres langages, du fait de l'utilisation intensive de la
pile pour 'passer' des données d'une partie de programme
à l'autre ( d'un mot à l'autre en Forth ), en
fait on les utilise lorsqu'on a une gestion de pile qui se
complique trop à vouloir les éviter. En Forth,
les variables doivent être déclarées,
c'est à dire qu'on doit signaler à Forth, qu'on
crée une variable, ainsi si on veut créer la
variable A, on écrira : VARIABLE
A , et A sera créée, et contiendra par
défaut la valeur 0. Pour
changer le contenu de la variable, on se sert du mot !
, oui vous lisez bien le point d'exclamation qui en Forth
se nomme 'store', et pour lire le contenu d'une variable on
utilise le mot @ , l'arobase
qui en Forth se nomme 'fetch'; nous allons illustrer tout
cela par un exemple en Forth, mais il nous faut un autre mot,
c'est ' \ ', l'anti-slash suivi
d'un espace qui indique au Forth que la suite de la ligne
constitue un commentaire, et ne doit pas être interprétée
( et ne nécessite donc pas d'être tapée
), donc exemple : ((maintenant que vous
savez qu'il faut revenir à la ligne pour plus de clarté,
nous n'allons plus indiqué les retours de lignes))
VARIABLE ESSAI \ Crée
la variable essai
ESSAI @ . \ Lit la variable ESSAI,
et affiche son contenu
3 ESSAI ! \ Affecte 3 dans ESSAI¬
ESSAI @ . \ Lit la variable ESSAI,
et affiche son contenu
Il est important de noter qu'une variable, même si son
nom est très long ( maximum 31 caractères),
ne représente en fait qu'une cellule mémoire
de 16 bits ( un mot ), que l'on peut invoquer indifféremment
par son nom ou son adresse. Par exemple, si nous tapons simplement
maintenant :
ESSAI . , Forth nous affichera
un chiffre ( par exemple 15666 -ça peut varier d'un
système à l'autre- ) qui est en réalité
l'adresse de la variable, et si nous faisons à présent
:
15666 @ . nous aurons 3 en réponse.
De même les mots @ lit
une variable et ! affecte une
variable de 16 bits.
Le système Forth lui même utilise des variables
pour son fonctionnement, ainsi, il existe une variable nommée
BASE, à laquelle il suffit
d'affecter la valeur de la base numérique dans laquelle
on veut travailler ( par défaut, au démarrage,
c'est la valeur 10 ). Donc si on veut passer en base 2, il
suffira de taper :
2 BASE !
le mieux étant même de créer un mot qui
fasse cela :
: BIN ( -- ) 2 BASE ! ; \ mot
permettant de passer en base 2
Il existe des mots prédéfinis permettant de
passer d'une base à l'autre, ce sont les mots :
DECIMAL (passe en base
10),
OCTAL (base 8 -pour les octets-),
HEX (base 16 hexadécimale
-pour les mots-).
BIN n'est pas défini d'origine.
Il faut noter que lorsqu'on est passé dans une base,
le retour à la base d'origine doit être demandé,
sinon on reste dans la dernière base affectée
à BASE (logique non ?).
Par exemple si on veut connaître la valeur hexadécimale
de 62, on tapera
62 HEX .
et on obtiendra l'affichage de 3E,
mais si ensuite on tape par exemple 55,
on le fera dans le système hexadécimal, ce qui
donnera si on fait à la suite DECIMAL
. la valeur 85 en base
10. Grâce a ce système de gestion des bases dans
Forth, on peut se créer une table de conversion décimal,
binaire, hexadécimal, il suffit de créer le
mot CVB (CVB pour conversion
de base -ou le nom que vous voudrez lui donner) :
: CVB ( -- ) DUP DUP |
\ on duplique deux fois le dernier nombre sur la pile |
. ." " |
\ on en a donc trois copies |
|
\ . affiche le nombre dans la base courante, ."
permet |
|
\ d'afficher une chaîne de caractères (
ici des espaces |
|
\ " termine la chaîne de caractères
a afficher |
BIN |
\ il faut l'avoir défini avant, passe en base
2. |
. ." " |
\ voir ci dessus. |
HEX |
\ passe en base hexadécimale |
. ." " |
\ voir ci dessus. |
CR |
\ 'Carriage Return' , Retour Chariot, renvoie à
la |
|
\ ligne. |
DECIMAL ; |
\ Repasse en base 10 avant de terminer la définition
du |
|
\ mot. |
Si maintenant on tape :
10 CVB¬
on aura :
10 1010 A
Si vous créez une table, il vous suffit d'aller de
0 à 15 en décimal, mais essayez 16 pour visualiser
ce qui se passe ensuite en base 2, et surtout en base 16 (pensez
alors au quartet). Ensuite vous essayerez 255 et 256 (pensez
alors à l'octet). Ensuite vous essayerez 32767 et -32767
(pensez alors au mot, et au problème de la représentation
du signe des nombres).
|
Les constantes
:
Il existe aussi une sorte de pseudo-variable en Forth, que
l'on appelle constante, qui elle, a une valeur définie
une fois pour toute par le mot : CONSTANT
. Par exemple si on veut définir la constante AGE
avec la valeur 25, on écrira
:
25 CONSTANT AGE¬
mais là, contrairement a une variable, on récupérera
la valeur de la constante en tapant simplement son nom, ici
on tapera : AGE ., et l'affichage
renverra 25.
|
ENTRAINEMENTS
(2):
Faire:
HELP VARIABLE
HELP !
HELP @
HELP BASE
HELP DECIMAL
HELP HEX
HELP OCTAL
HELP ."
HELP "
|
Un autre mot Forth utile :
SEE .
SEE permet de voir la définition d'un mot.
Donc, vous ferez aussi par curiosité :
SEE BIN SEE DECIMAL
SEE HEX SEE OCTAL
.
|
Personnalisation:
Comme nous l'avons déjà vu Forth utilise un
vocabulaire que l'on peut étendre en définissant
des mots nouveaux, j'aurais du dire des vocabulaires car il
y en a plusieurs, mais nous n'en avons besoin que d'un pour
le moment, c'est celui qui est présent au lancement
de TF83. Il y a un mot que vous pouvez essayer, c'est WORDS,
qui affiche le vocabulaire courant, et si vous frappez tout
de suite sur un touche, vous arrêtez le défilement,
et vous verrez que les mots en tête de liste sont ceux
que vous avez définis.
Vous avez peut être déjà noté un
problème, c'est que lorsque vous quittez TF83, et que
vous y retournez plus tard, tous les mots que vous aviez définis
n'existent plus. Pour remédier à ce problème
je vous propose la solution suivante ( il y en a d'autres,
mais vous les découvrirez plus tard par vous-même
) : Vous quittez TF83, vous le relancez, vous vérifiez
avec WORDS qu'il ne se souvient
plus des derniers mots que vous lui aviez appris, et ensuite,
nous allons définir le mot ED
( qui appellera le programme EDIT.COM du DOS ) :
: ED ( -- ) " program c:\windows \command \edit.com"
$EXECUTE ;
ensuite vous taperez les commandes suivantes :
SAVE-SYSTEM c:\forth \tf83 \tf_a_moi.exe¬
, puis vous allez retourner sous Windows, et vous allez supprimer
le raccourci que vous avez vers TFX386.EXE. Vous ouvrirez
le lecteur C, le répertoire Forth, le sous-répertoire
TF83, et vous sélectionnerez le fichier TF_A_MOI.EXE
que vous déplacerez sur le bureau, vous disposerez
alors d'un nouveau raccourci vers un système Forth
avec la commande ED intégrée,
et qui ne se perdra plus. L'utilité de ED,
est la suivante, vous pouvez désormais appeler EDIT.COM
en tapant : ED¬ Là
vous pouvez vous servir d'EDIT normalement, charger, écrire,
sauvegarder des fichier, etc.., et lorsque vous ferez 'Fichier''Quitter',
vous vous retrouverez directement sous Forth, en fait on a
juste remplacé l'éditeur par défaut de
Forth. Maintenant, lorsqu'on définira des mots, vous
pourrez les taper dans EDIT, et vous sauvegarderez les fichiers
sous le nom que vous aurez choisi ( pour les exemples ou les
exercices ). par exemple : EXEMP.FTH, l'extension .FTH
est importante car elle est reconnue par Turbo-Forth par défaut.
Par ailleurs, il serait bon que vous les enregistriez ( les
fichiers ) dans le répertoire c:\forth \tf83,
car TF83 ne reconnaît pas les noms longs de répertoire
ou de fichier de Windows, il ne connait que ceux du DOS à
8 lettres, un point et 3 lettres d'extension. Ainsi supposons
que nous créions un mot, nous tapons ED et nous sommes
sous EDIT.COM, là, nous tapons la définition
de notre mot :
: BASE? ( -- ) ." La base courante
est la base : " BASE @ DUP DECIMAL . BASE ! ;
Puis nous faisons 'Fichier''Enregistrer
sous' nous tapons le nom du fichier ( ici EXEMP.FTH
) nous sélectionnons le répertoire de sauvegarde,
et nous cliquons sur OK. Nous faisons 'Fichier''Quitter'
et nous sommes à nouveau sous TF83, là un WORDS
nous montre que BASE? n'existe
pas. Nous allons donc l'inclure a l'aide du mot INCLUDE
. Si EXEMP.FTH a bien été
enregistré sous c:\forth \tf83,
répertoire ou se trouve normalement TF_A_MOI.EXE,
il suffit de taper :
INCLUDE EXEMP¬ et un WORDS
nous montrera que tout se passe comme si on avait tapé
BASE? directement au clavier
sous TF. D'ailleurs vous pouvez essayer BASE? à ce
niveau là, en changeant la base courante, pour voir
s'il fonctionne bien. Dans le cas ou le fichier à charger
ne se trouve pas dans le même sous répertoire
que TF, il faut indiquer le chemin d'accès complet,
par exemple :
INCLUDE c:\forth \tf83 \essais \EXEMP.FTH¬
ou bien :
CHDIR c:\forth \tf83 \essais \ INCLUDE
EXEMP.FTH¬
L'avantage de ce système, vous l'avez déjà
deviné, c'est de pouvoir rappeler des mots déjà
défini, et de pouvoir corriger les éventuelles
fautes de frappe ou de programmation, et de pouvoir 'recharger'
le fichier corrigé, ou augmenté.
|
EXERCICE 11
:
Commenter la définition du mot BASE? pour voir si
vous avez
bien tout ce qui précède.
|
A présent, un peu de vocabulaire
supplémentaire
:
FORGET <mot> ( -- ), efface
les mots définis dans Forth par l'utilisateur, après
le mot <mot>, y compris celui ci. TF se retrouve alors
avec le vocabulaire qu'il avait avant la définition
de <mot>. Par exemple, définissons les mots suivants
:
: TOTO ( mot vide ) ;
: BECASSINE ( mot vide ) ;
: DONALD ( mot vide ) ;
si nous faisons WORDS¬ suivi d'une frappe rapide sur une
touche, les premiers mots qui apparaissent en haut à
gauche de l'écran sont dans l'ordre :
DONALD BECASSINE TOTO ...
faisons maintenant :
FORGET BECASSINE¬
un nouveau WORDS¬ affichera
désormais :
TOTO ...
HERE ( -- adr ), renvoie l'adresse
du premier emplacement libre du dictionnaire de Forth. C'est
là que nous commençons vraiment à jouer
avec l'outil qu'est le Forth, ca nous allons le faire se modifier
lui même.
FENCE ( -- ), Variable qui contient
l'adresse limite en dessous de laquelle une définition
ne peut plus être supprimée par FORGET
<mot>. Reprenons l'exemple
précèdent, après avoir défini
nos trois mots, si nous faisons :
HERE
|
\ nous empilons l'adresse du premier emplacement libre
dans le dictionnaire.
|
FENCE !
|
\ nous affectons l'adresse renvoyée par HERE
à la variable FENCE
|
|
\ autrement dit nous demandons à Forth de placer
la limite en dessous
|
|
\ de laquelle il ne doit plus supprimer les définitions
par FORGET au
|
|
\ niveau de DONALD.
|
Si maintenant, nous tentons de faire mettons
FORGET TOTO¬ , TF nous renverra
le message d'erreur suivant : "Partie
du dictionnaire protégée"
|
Continuons notre jeu avec
le dictionnaire de Forth, mais pour cela, il nous faut définir
quelques notions nouvelles sur
le fonctionnement de Forth :
comment est organisé un mot dans le dictionnaire ?
Un mot Forth est constitué de plusieurs parties accolées
les unes aux autres, dans TF, l'organisation est la suivante
:
-
un VFA ( View Field Adress
) adresse du champs de vue, qui sert a Forth pour faire
ses recherches avec HELP.
un LFA ( Link Field Adress
) adresse du champs de lien, qui pointe vers la définition
du mot précèdent dans le dictionnaire.
un NFA ( Name Field Adress
) adresse du champs de nom, qui contient le nom du mot.
un CFA ( Code Field Adress
) adresse du champs de code, qui contient le code machine
nécessaire à l'exécution du mot.
un PFA ( Parameters Field
Adress ) adresse du champs de paramètres, qui contient
les adresses des mots qui constituent la définition
du présent mot.
|
Le code ASCII:
c'est un code qui affecte une lettre à une valeur
numérique codée sur un octet (soit 256 valeurs).
En réalité, seuls les codes de 0 à 127
servent a coder l'alphabet majuscules/minuscules, les signes
de ponctuation et les nombres ( soit 7 bits ) , les autres
de 128 à 256 ( 8 bits ) sont les codes semi-graphiques.
Le code ASCII est très important, car de très
nombreuses choses en informatiques sont codées par
son intermédiaire. Ainsi, en Forth aussi, les mots
sont codés en ASCII, en ASCII pur, puisque Forth n'admet
pas les caractères semi-graphiques dans les noms de
mots. Donc les noms de mots sont codés à l'aide
d'octets dont le bit 7 est à 0.
Très souvent ( mais pas toujours, puisqu'il faut des
exceptions pour confirmer les règles, on commence les
numérotation à 0 ), il en est ainsi dans un
octet qui rappelons-le contient 8 bits. Par exemple un octet
contient la valeur 177 (décimale),
nous l'écrirons en binaire
: |
1 0 1 1
|
0 0 0 1
|
et nous numéroterons les bits
ainsi : |
7 6 5 4
|
3 2 1 0
|
|
Si j'ai séparé les 2 quartets, c'est pour
introduire la notion de poids fort et de poids faible : on
appelle par exemple ici les bits 7, 6, 5, 4 le quartet de
poids fort, parce que dans l'octet, ce sont eux qui représentent
la valeur la plus grande, et les bits 3, 2, 1, 0 le quartet
de poids faible, parce qu'ils représentent la valeur
la plus petite. Ainsi dans un groupe, le sous groupe le plus
à gauche est de poids fort, et le plus à droite
de poids faible, on parlera d'octet de poids faible et de
poids fort dans un mot de 16 bits, de mot de poids faible
et de poids fort dans un mot-long, etc... Attention, le fait
d'être de poids faible ne signifie pas négligeable
les humhum de poids faibles sont
tout aussi indispensables que ceux de poids fort, les uns
n'existent pas sans les autres. Dans des groupes de deux entités
ou plus, comme dans les octets de huit bits, chaque bit plus
à gauche que le ou les précédents a un
poids plus fort, si on parle par exemple des bits n°1
et 3, le bit n°3 a un poids plus fort que le n°1.
Revenons à nos noms de mots Forth qui ne contiennent
que des caractères codés en ASCII pur, avec
le bit de poids fort à 0, ce n'est pas tout à
fait vrai, puisque la dernière lettre du nom du mot
est codée en ASCII sur 7 bits, mais pour savoir que
c'est la fin du nom du mot, à sa création Forth
met le bit n°7 à 1, nous allons le vérifier
à l'aide des mots suivants :
C@ ( adr -- c ) \ lit un octet à l'adresse
adr(sur 16 bits) et l'empile
' <mot> ( -- cfa ) \ il s'agit de l'apostrophe
-prononcer tick- empile
\
l'adresse du champs de code du mot <mot>
>NAME ( cfa -- nfa ) \ empile l'adresse
du champs de nom en consommant celle
\
du champs de code.
EMIT ( c -- ) \ affiche le caractère correspondant
à la valeur empilée
Tapons maintenant la séquence suivante :
' DONALD¬ \ empile l'adresse de champs de
code du mot DONALD
>NAME¬ \ la transforme en adresse du champs
de nom
¬
\ l'affiche.
nous obtenons par exemple 31305 ( ça peut varier d'un
système à l'autre,
mais le principe reste identique, ajoutons 1 à cette
adresse pour nous
trouver sur l'adresse contenant la première lettre,
et faisons :
31305 c@ .¬ \ nous affichons la valeur contenue à
l'adresse 31305
31306 c@ .¬
31307 c@ .¬
31308 c@ .¬
jusqu'à 31311, en nous obtenons logiquement les valeurs
suivantes :
68, 79, 78, 65, 76, 196. Nous nous arrêtons à
196 puisque c'est une valeur
supérieure à 127, et que nous avons donc atteint
la fin du nom du mot Donc
dans la suite, nous soustrairons 128 à 196 pour obtenir
le rang ASCII de la
dernière lettre du nom du mot ( soit ici 196-128=68
).
Continuons notre expérience en tapant à présent
:
68 EMIT \ l'affichage renvoie : D
79 EMIT \ " " O
78 EMIT \ " " N
65 EMIT \ " " A
76 EMIT \ " " L
68 EMIT \ " " D
|
|
|
|
|