FORTH ET LES NOMBRES
(Chapitre 3 du livre d'apprentissage)


 

A. Empilage et dépilage des nombres entiers.

Le langage FORTH stocke les nombres sur une pile nommée "pile de données" ou "pile paramétrique". L'empilage d'un nombre est très simple:

55

empile le nombre 55. Pour dépiler ce nombre, il y a plusieurs méthodes. La plus simple consiste à afficher le contenu du dernier élément empilé:

.      affiche 55

Si vous empilez plusieurs nombres, voici ce qui se passe:

11 45 6543

Empilage du premier nombre

11  
Empilage du second nombre

45
11


le nombre 11 passe en dessous
Empilage du troisième nombre

6543
45
11


le nombre 45 passe en dessous.
le nombre 11 passe en 3e position

Le dépilage successif des nombres affiche ceux-ci dans l'ordre inverse de leur empilage:

. affiche 6543
. affiche 45
. affiche 11

Pour mieux visualiser le mécanisme d'empilage et de dépilage des nombres, pensez à une pile d'assiettes: la dernière assiette déposée sur la pile sera la première reprise.

A tout moment vous pouvez prendre connaissance du contenu de la pile de données sans avoir à provoquer le dépilage des valeurs qui y sont stockées en utilisant le mot .S:

1 2 3 .S affiche 1 2 3

Ce principe de rangement est appelé également pile LIFO (Last In, First Out) dans certains ouvrages écrits en anglais pour désigner une pile dont le mécanisme est: "dernier entré, premier sorti".

Avec TURBO-Forth, la quantité de nombres empilables est assez élevée, mais reste limitée. Si vous empilez trop de nombres, vous saturerez la pile de données. De même, toute tentative pour dépiler un nombre alors que la pile de données est vide, affichera un message d'erreur. Exemple:

ABORT . affiche le message d'erreur Pile vide

Si vous désirez connaître à tout instant le nombre d'éléments présents sur la pile de données, tapez STATUS? ON ou la touche spéciale Shift-F3 et le message de disponibilité OK sera précédé des indications suivantes:

0 (dec) OK

Le nombre débutant la ligne indique le nombre d'éléments figurant sur la pile de données:

0 (dec) OK entrez 25
1 (dec) OK entrez 75 12
3 (dec) OK entrez +
2 (dec) OK entrez .    affiche    87
1 (dec) OK ...etc...

L'indication entre parenthèses indique la base numérique courante du système. Elle peut être (dec) pour la base décimale (valeur par défaut), (hex) pour la base hexadécimale et (oct) pour la base numérique octale.

Cette option peut être désélectionnée par STATUS? OFF ou Control-F3.

Chaque nombre empilé ne peut être qu'un nombre entier au format 16 bits. Selon les cas, ce nombre peut être considéré signé ou non signé:

- signé ou non signé: paramètre de calcul arithmétique
- non signé: adresse 16 bits intra-segment

En format 16 bits signé, le bit de poids le plus fort indique le signe du nombre.

La valeur -1, déposée sur la pile en tant que valeur entière a la représentation binaire suivante:

Cette même valeur peut être affichée en valeur absolue en utilisant le mot U. à la place du mot . (point):

-1 U. affiche 65535

Selon que l'on considère les entiers 16 bits signés ou non, leur intervalle de définition est:

- 16 bits signés entre [-32768..32767]
- 16 bits non signés entre [0..65535]

L'utilisation d'un nombre quelconque situé en dehors de cet intervalle n'aura aucune signification:

100000 . ou
-100000 U.     affichera une valeur sans rapport apparent avec 100000.

Cette valeur résiduelle correspond à la partie poids faible sur 16 bits du nombre 100000 et n'ayant pas débordé lors de son empilage sur la pile de données.

Ceci n'a aucune utilisation pratique et peut être comparable à la tentative d'hébergement d'une moissonneuse batteuse dans un enclos réservé aux bicyclettes, avec pour vous le risque en moins de ne pas être poursuivis par des propriétaires de vélos endommagés par cette maneuvre plus que douteuse. Cette limitation peut sembler contraignante au premier abord, mais les performances de FORTH sont à ce prix.

Le traitement des nombres entiers est beaucoup plus rapide que celui de nombres exprimés dans des formats différents. Vous constaterez, à l'usage, que les nombres entiers suffisent dans la majorité des cas. Nous verrons plus loin, que FORTH n'est pas limité au traitement des nombres entiers 16 bits: il suffit d'exprimer des données complexes sur plus d'une cellule de la pile.

Si vous êtes totalement débutant en FORTH, prenez le temps nécessaire à bien comprendre ce qu'est la pile de données, son mécanisme et son évolution: la notion de pile est certainement la plus importante du langage FORTH.

 

B. opérations arithmétiques élémentaires.

Les opérateurs arithmétiques + - * et / agissent sur les deux valeurs situées au sommet de la pile de données. Les valeurs traitées sont toujours des entiers 16 bits signés.

1.Somme de deux nombres entiers.

Pour additionner deux nombres, il faut d'abord les déposer sur la pile de données:

22 44 + . affiche 66

Une fois empilés 22 et 44, le mot + opère l'addition de ces deux valeurs et le mot . (point) affiche le résultat.

55 1 + 3 + . affiche 59 et peut aussi s'écrire
55 1 3 + + .

L'addition est commutative: les valeurs peuvent être déposées sur la pile de données dans n'importe quel ordre:

55 22 + est équivalent à
22 55 +

Ce principe de calcul est appelé NOTATION POLONAISE INVERSE (RPN dans la littérature anglaise, pour Reverse Polish Notation). On peut aussi additionner deux nombres entiers non signés, à condition de visualiser le résultat à l'aide du mot U. au lieu de . (point).

35000 10 + U.

Il est également possible de faire la somme de deux nombres de signe différent:

10 -5 + .    affiche    5
-5 10 + .    affiche    aussi 5

Selon que l'on traite des valeurs considérées comme signées ou non, les intervalles de définition des résultats doivent respectivement se situer dans [- 32768..32767] ou [0..65535]. Tout résultat situé hors de ces intervalles n'aurait aucun sens.

TURBO-Forth dispose également des primitives 1+ et 2+ qui incrémentent respectivement la valeur située au sommet de la pile de données de 1 ou deux unités:

10 1+ est équivalent à
10 1 +

2. Soustraction de deux nombres entiers.

Soit deux nombres a et b. La différence de deux nombres sera écrite en FORTH sous la forme:

a b -     pour      a-b

La soustraction n'est pas commutative.

10 3 - .       affiche      7
3 10 - .       affiche    -7

Les primitives 1- et 2- décrémentent respectivement la valeur située au sommet de la pile de données de 1 ou deux unités:

10 1-    est équivalent à
10 1 -

3.Produit de deux nombres entiers.

Soit deux nombres a et b. Le produit de deux nombres sera écrit en FORTH sous la forme:

a b *    pour    a*b

La multiplication est commutative:

7 5 * .    ou
5 7 * .    affiche    35

Les primitives 2* et 8* multiplient respectivement la valeur située au sommet de la pile de données par deux ou huit:

5 2*     est équivalent à     5 2 *

4. Quotient de deux nombres entiers.

Pour la division, seul le quotient entier est conservé sur la pile de données:

22 7 / .    affiche    3

La division n'est pas commutative:

15 5 / .    affiche    3
5 15 / .    affiche    0

Le reste de la division peut être obtenu en appliquant la fonction modulo:

22 7 MOD .    affiche    1

La fonction modulo peut servir à déterminer la divisibilité d'un nombre par un autre:

: DIV? ( n1 n2 ---)
  OVER OVER MOD CR
  IF SWAP . ." n'est pas "
  ELSE SWAP . ." est " THEN
  ." divisible par " . ;

22 7 DIV?    affiche    22 n'est pas divisible par 7
22 11 DIV?   affiche   22 est divisible par 11

La fonction /MOD combine les actions de / et de MOD:

22 7 /MOD . .    affiche    3 1

Par parenthèse, pour les BASICois de longue date incomplètement convaincus par FORTH, voici la même fonction transcrite dans leur patois:

? INT(22/7),22-(INT(22/7)*7) ce qui est évident... pour les habitués. ou
? INT(22/7),22 MOD 7 si votre BASIC a été rafraîchi récemment.

5. Produit et quotient de trois nombres.

Si on essaye une opération du type suivant:

30000 3 * 10 / .

on risque d'être quelque peu surpris par le résultat. Mais tout s'explique, car le produit calculé en premier délivre une valeur dont la capacité est supérieure à celle admise par les valeurs 16 bits signées. Pour traiter ces cas particuliers, on utilisera de préférence le mot */ qui combine les opérations de multiplication et de division, mais traite le résultat transitoire de la multiplication au format double précision. Exemple, soit à calculer le prix TTC d'une marchandise (TVA à 18,6 %), on définira le mot TTC comme suit:

: TTC ( n1 --- n2)
DUP 186 1000 */ + ;

100 TTC .   affiche    118

Les valeurs traitées étant exprimées en centimes.

La primitive */MOD a les mêmes propriétés que */, mais délivre le quotient et le reste de l'opération.

Une autre application immédiate et pratique des notions déjà exprimées, est la conversion des degrés Fahrenheit et Celsius:

-la conversion des degrés Fahrenheit en degrés Celsius obéit à la formule
  °C=(°F-32)*5/9
-la conversion des degrés Celsius en degrés Fahrenheit obéit à la formule
  °F=9/5*°C+32

: C>F ( °C --- °F)
9 5 */ 32 + ;

: F>C ( °F --- °C)
32 - 5 9 */ ;

37 C>F .    affiche    98 (les résultats sont arrondis)

6. Traitement des expressions algébriques.

Les opérations peuvent être chaînées, mais une opération en notation algébrique comportant des parenthèses doit être convertie en notation RPN en tenant compte de l'ordre de priorité des opérations. FORTH n'utilise pas les parenthèses dans les opérations arithmétiques:

soit l'expression algébrique         ( 2 + 5 ) * ( 7 - 2 )
elle s'écrit en FORTH                 2 5 + 7 2 - *

Lors d'une opération de conversion de notation algébrique infixée en notation polonaise inverse, commencez toujours par le niveau de parenthèse le plus imbriqué et par la gauche. Ecrivez la transcription en notation polonaise inverse de chaque opération sur des lignes séparées, successivement de haut en bas, en les mettant dans le prolongement de l'expression algébrique exprimée dans la formule initiale:

En reprenant chaque niveau dans l'ordre, on réécrit la formule:

2 5 + 7 2 - * 5 2 + 3 * /

C'est choquant? Mais tous les interpréteurs/compilateurs travaillent ainsi lorsqu'ils ont à évaluer une formule algébrique. En notation algébrique, les parenthèses ne servent qu'à isoler une expression sous forme de sous-expression qui devient membre d'une expression plus générale.

En informatique comme en arithmétique, un opérateur travaille toujours sur deux opérandes et seulement deux opérandes simultanément. Le résultat d'une opération portant sur deux opérandes délivre une valeur qui peut devenir à son tour opérande d'un autre opérateur. L'ordre d'exécution des opérandes et des opérateurs est fondamental:

notation algébrique
polonaise inverse
(2+3)*5
2+(3*5)
2 3 + 5 *
2 3 5 * +   ou   3 5 * 2 +

 

Tous les problèmes arithmétiques peuvent être résolus de cette manière; ce n'est qu'une question d'habitude. L'exemple donné précédemment illustre parfaitement la rigueur dont doit faire preuve le programmeurs Forth. Cette rigueur garantit un fonctionnement sans ambiguïté des programmes, quel que soit leur niveau de complexité.

 

C.Manipulation des données sur la pile

La pile de données est l'élément fondamental du langage FORTH pour le traitement de données. Son fonctionnement est identique à celui de la pile gérée par le micro-processeur. Dans certaines situations, les données traitées par les différentes définitions doivent être réordonnées ou dupliquées.

Le mot DUP duplique le contenu du sommet de la pile de données:

10 DUP . .   affiche   10 10
5 DUP * .    affiche   25

Le mot OVER duplique le second élément de la pile de données:

5 15 OVER . . .   affiche   5 15 5

Le mot SWAP inverse les deux éléments du sommet de la pile de données:

1 3 SWAP . .   affiche   1 3

Le mot ROT effectue une rotation sur les trois éléments situés au sommet de la pile de données:

1 2 3 ROT . . .   affiche   1 3 2

Le mot -ROT effectue une rotation inverse sur trois éléments. Son comportement est similaire à l'exécution de deux ROT successifs.

Le mot PICK dépose au sommet de la pile de données le nième élément de la pile de données, n non compris. La base de départ pour le comptage des éléments à traiter est 0 et non 1, l'élément numéro zéro étant situé immédiatement après le paramètre traité par PICK. La séquence 0 PICK est similaire à DUP, 1 PICK à OVER. Il n'y a pas de traitement d'erreur si n est supérieur au nombre d'éléments déposés sur la pile de données. Exemple:

1 2 3 4 5 6    4 PICK    empile 2 car 6 est l'élément n°0, 5 l'élément n°1, etc...

Le mot ROLL effectue une rotation sur les n premiers éléments de la pile de données, n non compris. Comme pour PICK, la base de départ pour le comptage des éléments à traiter est 0:

1 2 3 4 5 6 4 ROLL . . . . . .    affiche    2 6 5 4 3 1

Voici quelques exemples d'utilisation de ces manipulateurs de pile de données:

: AU-CARRE ( n --- n2)
  DUP * ;

Le mot AU-CARRE élève un nombre entier quelconque au carré:

2 AU-CARRE .   affiche   4
3 AU-CARRE .   affiche   9
4 AU-CARRE .   affiche  16

: AU-CUBE ( n --- n3)
   DUP DUP * * ;

Le mot AU-CUBE élève un nombre entier quelconque au cube:

2 AU-CUBE .   affiche   8
3 AU-CUBE .   affiche  27

Attention, n'utilisez pas des valeurs trop élevées, car un résultat supérieur à 32767 devient faux. Ayez toujours à l'esprit que les données que vous traitez sont des entiers 16 bits, donc de capacité limitée. Nous verrons ultérieurement comment traiter des nombres plus importants.

Vous avez peut-être déjà feuilleté le manuel ou consulté le dictionnaire FORTH à la recherche de INPUT pour faire un programme comme en BASIC. Eh bien soyez rassuré, INPUT n'existe pas! (ah, bon, vous n'êtes pas rassuré...?). Allons, nous ne voulions pas vous peiner. TURBO-Forth a quand même plus d'un tour dans son sac:

80 STRING TAMPON$
: ELEVE-AU-CARRE
  CR ." Entrez un nombre: " TAMPON$ INPUT$
  CR ." Elevation au carré: " TAMPON$ $EXECUTE
  DUP * . CR ;

Voilà, vous l'avez, votre programme comme en BASIC! Bien entendu, notre petit artifice a consisté à faire transiter notre nombre saisi au clavier par une variable chaîne préalablement déclarée, puis dont le contenu a été évalué. Essayez ceci maintenant:

2 CONSTANT DEUX
3 CONSTANT TROIS
ELEVE-AU-CARRE

et si vous entrez DEUX lorsque le programme demande un nombre, il fonctionnera très bien. Par l'intermédiaire de $EXECUTE, TURBO-Forth évalue non seulement un nombre, mais aussi les expressions:

ELEVE-AU-CARRE

et entrez DEUX TROIS + vous affichera le carré de cinq.

Toute cette petite digression pédagogique avait pour seul but de marquer encore plus la distance entre FORTH et les autres langages. En voulant faire comme BASIC, on a alourdi la procédure d'élévation au carré. La philosophie du langage FORTH tend à la simplicité. Il faudra toujours privilégier l'aspect sobre et un peu rustique des définitions. Un mot traitant une donnée passée par la pile de données n'est pas moins efficace qu'un programme alambiqué écrit en N'IMPORTE- QUOI-D'AUTRE (C, PASCAL, FORTRAN, COBOL, etc... et bien s-r B-A-S-I-C).

 

D. Passage de paramètres par la pile de retour.

A coté de la pile de paramètres, il existe dans FORTH une deuxième pile, appelée pile de retour parce qu'elle sert à l'interpréteur interne à retrouver l'adresse de retour à chaque appel d'une procédure.

Il y a parfois des cas extrêmes où l'on peut être amené à stocker un ou plusieurs paramètres ailleurs que sur la pile de données, ceci pour simplifier quelque peu certaines manipulations scabreuses. la solution la plus commode, parmi d'autres, est la pile de retour. Cette pile est accessible par les mots >R et R> moyennant quelques précautions pour ne pas compromettre le fonctionnement de cette pile interne.

Le mot >R transfère un nombre entier de la pile de données vers la pile de retour. Le mot R> transfère un nombre entier de la pile de retour vers la pile de données.

Une opération >R  R> est nulle. En fin de définition, il doit y avoir autant de >R que de R> sous peine de perturber quelque peu le déroulement normal de votre définition. Exemple d'utilisation:

: ^2 ( n --- n^2)   \ élévation au carré
  DUP >R   \ transfert de la copie sur pile de retour
  CR ." Le carré de " .   \ affichage valeur initiale
  ." est " R> DUP * .  ;   \ récupération valeur déposée sur pile retour
    \ et affichage de son carré
   

Ici, les mots >R et R> ont servi à mémoriser la valeur initiale déposée sur la pile de données. Nota: si vous essayez cet exemple, ne tapez pas les commentaires qui suivent le caractère   \, FORTH ne les compilant pas.

Si aucune donnée n'a été transférée depuis la pile de données vers la pile de retour, l'utilisation du mot R> transfère l'adresse d'exécution du prochain mot à exécuter au sommet de la pile de données:

: PROCHAIN-MOT ( --- adr)
  R> DUP >R ;

Mais ceci n'a réellement d'intérêt que si vous devenez un barbu de la programmation en FORTH et que vous cherchez à comprendre les mécanismes subtils qui animent ce langage.

 

E. Contrôle de l'affichage des nombres entiers.

En FORTH, les entiers 16 bits déposés sur la pile de données peuvent être affichés par exécution du mot . (point). Mais d'autres mots permettent d'exécuter un affichage plus présentable.

Le mot .R affiche un nombre 16 bits signé cadré à droite dans un champ de n caractères. Exemple:

3 10 .R         affiche          3 (3 précédé de 9 espaces)
101 10 .R     affiche      101 (101 précédé de 7 espaces)

Et dont voici une application très pratique:

: C>F ( °C --- °F)       \ Conversion Celsius en Fahrenheit
  9 5 */ 32 + ;

: .TREMPE ( °C ---)      \ Affiche °C et °F formatés
  DUP 6 .R ." °C "
  C>F 6 .R ." °F" ;

: TREMPE-ACIER ( ---)       \ Table des températures de trempe
  CR ." COULEURS DE TREMPE DE L'ACIER:" CR
  CR ." rouge foncé "          680 .TREMPE
  CR ." rouge cerise foncé" 740 .TREMPE
  CR ." rouge cerise "         770 .TREMPE
  CR ." rouge cerise clair"   800 .TREMPE
  CR ." rouge clair "            850 .TREMPE
  CR ." rouge très clair "      900 .TREMPE
  CR ." rouge jaune "          950 .TREMPE
  CR ." jaune "                  1000 .TREMPE
  CR ." jaune clair "           1100 .TREMPE
  CR ." jaune blanc "          1200 .TREMPE
  CR ." blanc "                   1300 .TREMPE
  CR CR ;

Le mot U.R procède de la même manière que .R, mais affiche le nombre entier non signé:

1 10 U.R     affiche    1
-1 10 U.R   affiche     65535

Exemple, soit à afficher une suite d'adresses en hexadécimal et l'équivalent en décimal entre parenthèses:

: .H(D) ( n ---)
  BASE @ >R      \ sauvegarde base numérique courante
  DUP HEX 4 U.R      \ affichage en hexadécimal dans un champ de 4 car.
  SPACE ." ("         \ affichage d'un espace et parenthèse ouverte
  DECIMAL 5 U.R      \ affichage en décimal dans un champ de 5 caractères
  ." )"      \ affichage de la parenthèse fermée
  R> BASE ! ;      \ restauration base numérique courante
DECIMAL
CR 256 .H(D)       affiche        100    (    256)
CR 65535  .H(D)   affiche    FFFF    (65535)
HEX
CR FF .H(D)        affiche          FF        ( 255)
CR FFFF .H(D)   affiche      FFFF     (65535)

 

F. Les nombres double précision.

FORTH ne connaît pas les nombres en virgule flottante. Cependant, des routines peuvent être compilées pour exécuter des calculs sur ce type de nombres, mais ce sera au détriment de la vitesse de traitement. Si vous voulez traiter des quantités importantes, comme votre compte en banque ou le prix de votre prochaine voiture, vous pouvez utiliser les nombres double précision également nommés nombres 32 bits. Ceux-ci se distinguent des nombres entiers 16 bits en y introduisant un point, une virgule ou une barre de fraction:

135246. D.    affiche    135246
135246, D.    affiche    ;135246

Le point, la virgule ou la barre de fraction peuvent être placés ailleurs qu'à l'extrémité du nombre:

135,246 D.    affiche    135246

Les opérations élémentaires exécutables sur les nombres 32 bits sont l'addition et la soustraction:

3. 5. D+    correspond à    3 + 5
3. 5. D-    correspond à    3 - 5

Les nombres double précision 32 bits situés au sommet de la pile peuvent être affichés par les mots suivants:

D.    prononcer 'D-point'. Affiche un nombre double précision signé.
UD.    prononcer 'U-D-point'. Affiche un nombre double précision non signé.
D.R    prononcer 'D-point-R'. Affiche un nombre double précision signé cadré à droite dans un champ de n caractères.
UD.R    prononcer 'U-D-point-R'. Affiche un nombre double précision non signé cadré à droite dans un champ de n caractères.

Exemples:

5. D.    affiche    5
-1. UD.    affiche    4294967295
10. 12 D.R    affiche    10
35.3 12 UD.R    affiche    353

Un nombre entier 16 bits signé peut être transformé en nombre 32 bits signé en exécutant le mot S>D. Exemples:

10 S>D D.    affiche    10
-5 S>D D.    affiche    -5

Pour transformer un nombre entier 16 bits non signé en nombre 32 bits non signé, il suffit d'empiler la valeur 16 bits 0 sur la pile après empilage du nombre entier 16 bits non signé. Exemple:

10 0 D.    affiche    10
-5 0 D.    affiche    65531 L'opération inverse est possible si la valeur 32 bits est comprise entre 0 et 65535:

10. DROP .    affiche    10

Quand un nombre 32 bits est déposé sur la pile de données, la variable DPL conserve la position du point décimal; si c'est un nombre 16 bits qui est déposé sur la pile de données, la variable DPL contient la valeur - 1. On peut exploiter cette valeur pour définir un mot assurant une conversion conditionnelle:

: ?S>D ( d ou n --- d)
DPL @ 0< IF S>D THEN ;
10 ?S>D D.    affiche        10
10. ?S>D D.    affiche    10

Il est intéressant de comparer les valeurs de DPL pour différentes positions du point décimal lors du traitement d'un nombre 32 bits:

3314. DPL @ .    affiche    0
331.4 DPL @ .    affiche    1
33.14 DPL @ .    affiche    2
3.1.4 DPL @ .    affiche     1
      (seule la position du second point est conservée dans DPL)

Les opérations de multiplication et de division 32 bits ne sont pas définies à l'exception des mots D2* et D2/:

10. D2* D.    affiche    20
10. D2/ D.    affiche    5

Mais avec les primitives de FORTH, il n'y a aucun problème pour définir des mots permettant de multiplier un nombre 32 bits par trois, quatre, cinq ou plus le cas échéant:

: D3* ( d --- d*3)
  2DUP 2DUP D+ D+ ;
: D4* ( d --- d*3)
  D2* D2* ;
: D5* ( d --- d*5)
  2DUP D2* 2SWAP D3* D+ ;     etc...

 

G. Opérations mixtes 16/32 bits.

Les nombres 32 bits sont des valeurs généralement trop importantes pour qu'il soit intéressant de leur appliquer un traitement du type produit ou quotient. Toutefois, certains opérateurs arithmétiques mixtes permettent d'exécuter ces opérations.

Le mot MU/MOD divise un nombre 32 bits non signé par un nombre 16 bits signé; laisse sur la pile le quotient 32 bits non signé et le reste signé. Exemple:

11. 2 MU/MOD D. .    affiche    5 1

Le mot M/MOD divise un nombre 32 bits signé par un nombre 16 bits signé; laisse sur la pile le quotient et le reste au format 16 bits signés. Exemple:

-12. 2 M/MOD . .    affiche    -6 0

Le mot U*D multiplie deux nombres 16 bits non signés et laisse sur la pile le résultat au format 32 bits non signé. Exemple:

10 30 U*D D.    affiche     300

Le mot *D multiplie deux nombres 16 bits signés et laisse sur la pile le résultat au format 32 bits signé. Exemple:

-10 30 *D D.    affiche    -300

 

 

-- hautdepage -- page d'accueil --