			Le Pr‚-processeur
			*****************

1 Inclusion d'un fichier lors de la compilation
***********************************************

	On peut assembler au pr‚alable une routine et l'inclure dans un programme
FORTH au moment de la compilation, en liaison avec COMP.PRG, cecla
donnera un programme monobloc (le fichier est inclus une fois et fait partie de
l'ex‚cutable). Il est bien sur possible d'inclure autre chose que du code ex‚cutable.
	Pour le code ex‚cutable, plut“t que de chosir un format objet (de certains
compilateurs) pusiqu'ils ne sont pas tous ‚quivalents, j'ai choisi d'inclure
directement des fichiers ‚x‚cutables Atari.

>include
--------

	m  >include  "chemin\fichier.ext"

	inclut un fichier … l'int‚rieur du programme … l'emplacement courant
du dictionnaire. Le mot de commande m est un masque de bits:
	bit 0	: 0=un fichier PRG
		  1=autre
	bit 1	: 0=s'assurer de la parit‚ du pointeur aprŠs chargement
		  1=ignorer parit‚
	bit 2    : 0=reloger les adresses absolues
		  1=ne pas reloger

	Voir ci dessous les diff‚rentes possibilit‚s offertes par cette
commande.

Inclusion d'une routine dans un mot assembl‚

	Exemple, dans un mot je veux d‚caler une valeur de 3 bits vers la
droite (division rapide par 8). Je pr‚pare en assembleur le programme
suivant:

	text

	move.l (a6),d0	; la valeur prise sur la pile
	asr.l #3,d0		; d‚cale
	move.l d0,(a6)	; remet sur la pile

	end

	Que j'assemble vers C:\DIV8.PRG

	Il ne reste plus qu'… ‚crire en FORTH:



:: essai
	p @
	0 >include "C:\DIV8.PRG"
	p !
;

	Ce mot divisera la variable p par 8!

A noter:
	* pas d'espaces dans la chaine du nom de fichier
	* les sections TEXT et DATA sont incluses dans la d‚finition, … vous de
'sauter' par dessus les datas si le mot doit se poursuivre.

Inclusion de d‚finitions de mots en assembleur

	Si le mot entier doit ˆtre d‚finit en assembleur, on doit utiliser une
structure particuliŠre du fichier PRG:
	* la zone TEXT contient les d‚finitions et les donn‚es
	* la zone DATA contient les adresses et les noms des mots cr‚‚s, elle
est donc r‚serv‚e.

	Exemple, on peut pr‚parer en assembleur les mots suivants:

	text

plus8:
	dc.w 437		; tous les mots assembl‚s en FORTH commencent
				; par ce code.
	addq.l #8,(a6)	; ajoute 8 … la valeur sur la pile
	rts

moins8:
	dc.w 437
	subq.l #8,(a6)	; soustrait 8 … la valeur sur la pile
	rts

salut:
	dc.w 437
	lea chaine(pc),a0
	move.l a0,-(a6)	; empile l'adresse d'une chaine
	rts

	dc.w 26		; en FORTH, une chaine est pr‚c‚d‚e de sa
				; longueur maximale.
chaine: dc.b "Salut, je suis assembl‚!",0
	even
	data

	dc.b "ADD_DEFS"	; texte obligatoire signalant une s‚rie de
				; d‚finitions
	dc.l plus8,moins8,salut,-1
			; suite des adresses et -1 pour terminer
	dc.b "8+",0,"8-",0,"salut",0
			; suite des noms s‚par‚s par un '0'

	end

	Que j'assemble vers "C:\DEFS.PRG"

	Il suffit d'ajouter dans le programme FORTH:

	0 >include "C:\DEFS.PRG"

	pour disposer des mots '8+',  '8- 'et 'salut'.

A noter:
	* pas d'espaces dans la chaine du nom de fichier
	* seule la zone TEXT est incluse, la zone DATA est simplement lue mais
non conserv‚e.
	* laisser toujours … 0 le bit 2 du mot de commande si votre programme
n'est pas relogeable (accŠs non relatif au PC).

Inclusion 'brute' d'un fichier autre que PRG

	Le problŠme r‚side dans la r‚cup‚ration de l'adresse … laquelle a ‚t‚
charg‚ le fichier. Le plus simple est d'utiliser l'un des codes internes du
FORTH, il s'agit de [var], utilis‚ dans une variable.
	Une variable est construite ainsi:
	[var]
	+valeur sur 4 octets
	L'action de [var] est de fournir sur la pile l'adresse de la zone qui le
suit imm‚diatement! Ainsi:

: bloc
	[var]
	1 >include "C:\IMAGE.IMG"
;
	incluera une image dont l'adresse est obtenue en ex‚cutant bloc.
Malgr‚ l'utilisation de : ... ; (mode interpr‚t‚), le mot bloc est parfaitement
assemblable car il est reconnu comme une variable (il commence par [var]!).
	Aucun mot ne sera ex‚cut‚ aprŠs [var] car il contient en lui mˆme
l'‚quivalent de ';' (fin de mot).
	Ainsi:

: bloc
	[var]
	1 >include "C:\IMAGE.IMG"
	16 +
;
	ne renverra pas l'adresse de l'image augment‚e de 16, car la fin du
mot est atteinte avec [var].

En r‚sum‚

	* pour inclure un programme le mot de commande est 0
	* pour inclure un autre fichier, le mot de commande est 1
	* si il s'agit d'un programme:
		la section DATA commence par "ADD_DEFS":
			il s'agit d'inclure les d‚finitions de la zone TEXT dont les
			adresses et les noms figurent dans la zone DATA.
		la section DATA ne commence pas par "ADD_DEFS":
			il s'agit d'inclure les zones TEXT et DATA comme une
			partie d'une d‚finition d‚j… commenc‚e.
	* n'utiliser le bit 1 du mot de commande (ignorer parit‚ du dicco) qu'en
connaissance de cause: sur un 68000 les accŠs mots … une adresse impaire
provoquent une erreur de bus, sur tous les 680X0, une instruction assembleur doit
commencer … une adresse paire.

Pour aller plus loin

	On peut d‚finir des variables dans un fichier PRG:

	text

var:
	dc.w 140		; c'est le code de [var]
	dc.l 1234		; la variable est initialis‚e … 1234

	data
	dc.b "ADD_DEFS"
	dc.l var,-1
	dc.b "ma_variable",0

	end

	On peut faire du FORTH en assembleur...

	text

forth:
	dc.w 96		; code de 'pad'
	dc.w 92		; code de 'len'
	dc.w 124		; code de '.'
	dc.w 79		; code de ';'

	data
	dc.b "ADD_DEFS"
	dc.l forth,-1
	dc.b "pad_len",0
	end
	Est ‚quivalent …:
: pad_len
	pad len .
;
	qui affiche la longueur de la chaine contenue dans pad.

	On peut ‚galement mˆler dans un mˆme mot une partie interpr‚t‚e et une
partie assembl‚e:

	text

	move.l (a6)+,d0	; la valeur sur la pile
	btst #0,d0		; le chiffre des unit‚s
	beq.s .lb0
	moveq #0,d0		; renvoit 0 si le nombre est impair
	move.l d0,-(a6)
	rts
.lb0:
	moveq #1,d0		; renvoit 1 si il est pair
	move.l d0,-(a6)
	rts

	end

	Assembl‚ vers C:\PAIR.PRG.

	Ensuite:

: parit‚
	p @ [ass]
	0 >include "C:\PAIR.PRG"
;

	renverra 0 ou 1 selon que la valeur de p est impaire ou paire. De
mˆme que pour [var], le code [ass] (celui qui vaut 437) contient en lui
mˆme l'‚quivalent de ';', ainsi, c'est le dernier mot ex‚cut‚ dans parit‚. On ne
pourra pas appeler parit‚ depuis un mot assembl‚ (puisque le d‚but de sa
d‚finition est interpr‚t‚e).

Utiliser des variables d‚finies en FORTH

	Si la variable est d‚finie dans la partie FORTH du programme, il se pose le
problŠme de fournir son adresse … la partie assembleur si elle doit y acc‚der. Le
plus simple est de d‚finir une routine 'init' … qui on donnera ces pr‚cieux
renseignements qui seront sauv‚s et accessibles aux autres routines:

	text

init:
	dc.w 437
	lea adresses(pc),a0
	move.l (a6)+,(a0)+	 ; r‚cupŠre deux adresses et les range
	move.l (a6)+,(a0)+
	rts

adresses: dc.l 0,0		; place pour deux adresses: une variable et pad

majusc:
	dc.w 437
	lea adresses(pc),a0
	move.l (a0)+,a1	; adresse de la variable
	move.l (a0)+,a2	; adresse de pad
	move.l (a6)+,a0	; adresse d'une chaine
	move.l a2,-(a6)	; renvoit pad sur la pile
	moveq #0,d1		; 0 caractŠres au d‚part
.lb0:
	move.b (a0)+,d0	; un caractŠre
	beq.s	.lb1		; si nul, fin de chaine
	addq.w #1,d1	; compte
	and.b #$DF,d0	; en majuscule
	move.b d0,(a2)+	; dans pad
	bra.s .lb0		; continuer
.lb1:
	move.l d1,(a1)	; longueur de chaine renvoy‚e dans la variable
	rts

	data
	dc.b "ADD_DEFS"
	dc.l init,majusc,-1
	dc.b "init",0,"majusc",0

	end

	Assembl‚ vers "C:\DEFS.PRG".

	Ainsi:

variable Longueur

0 >include "C:\DEFS.PRG"

>comp

pad Longueur init	\ permet au mot 'majusc' de tourner correctement

" Coucou" majusc	\ renvoit sur la pile pad contenant "COUCOU" et la
			\ longueur 6 dans la variable Longueur.



2 Pr‚parer le source assembleur sous l'Editeur
***********************************************

	Pour faciliter la mise au point d'un programme, le texte assembleur
peut-ˆtre ‚crit sous l'‚diteur FORTH, export‚ et assembl‚ lors de la compilation:

>export
-------

	m >export "chemin\fichier.ext"
	....
	>comp

	Le mot >export permet d'envoyer dans un fichier texte toutes les
lignes le suivant jusqu'au prochain >comp (qui doit ˆtre le premier mot de
sa ligne!) Le mot de commande m ne contient que la valeur du flag (voir
>true et >false).

3 Utilisation d'un assembleur ext‚rieur
***************************************

	Une fois le code tap‚ siour l'‚diteur et export‚, il peut ˆtre assembl‚
directement … partir du FORTH lors de la compilation, c'est le mot >exec qui se
charge d'appeler l'assembleur.

>exec
-----

	m >exec "chemin\prog.ext"
	"ligne de commande"

	ex‚cute le programme sp‚cifi‚ en lui transmettant la ligne de
commande (qui se trouve obligatoirement sur la ligne suivante).
	le mot m:
	bit 0	: 0=appui d'une touche aprŠs l'ex‚cution du programme
		   1=ne pas attendre
	bit 1	: 0=ERREUR si le programme renvoit une valeur positive
		   1=ne pas signaler d'erreur
	bit 2	: 0=ERREUR si le programme renvoit une valeur n‚gative
		   1=ne pas signaler d'erreur
	bit 3	: 0=fermer la fenˆtre FORTH le temps de l'ex‚cution
		   1=ne pas tenir compte de la fenˆtre

	Dans tous les cas, une valeur nulle renvoy‚e par l'assembleur ne
g‚nŠre pas d'erreur. La rŠgle voudrait que seules les valeurs n‚gatives
correspondent … des erreurs, mais certains programmes renvoient un code
positif. Ainsi, les bits 1 et 2 permettent de s'adapter … toutes les situations.
	En cas d'attente de touche (bit 0 = 0), l'appui sur 'ESC' interrompt le
traitement comme une erreur.




4 Compilation conditionnelle, les Flags
***************************************

	Si on compile plusieurs fois de suite un programme FORTH sans avoir
modifi‚ les parties export‚es, il est inutile de les re-exporter et de les re-assembler
avec les commandes >export et >exec.
	Ainsi, on dispose d'une compilation conditionnelle rudimentaire, mais
suffisante. Le mot de commande 'm' des trois instructions >export, >exec,
>include, peut contenir le num‚ro d'un flag … tester pour valider ou ignorer
l'action. Ce flag est signal‚ dans le mot sup‚rieur (bits 16 … 31) de 'm':

>true
-----
	n  >true  : valide le flag n (de 1 … 15). Au d‚marrage, tous les flags
sont 'vrais' par d‚faut.

>false
------
	n >false  : invalide le flag n (de 1 … 15).

exemples:
	%h40000 >export "f:\test.s"

	n'exportera que si le flag 4 est vrai. En prenant l'oppos‚ de 'm', on ne
valide l'op‚ration que si le flag est faux:

	%h-20008 >exec "F:\assemble\asm.ttp"
	"f:\test.s"

	n'assemble que si le flag 2 est faux, le 8 correspond au bit 3, ne pas
fermer la fenˆtre FORTH lors de l'ex‚cution.

5 Autres Liens Ext‚rieurs
*************************

	On peut trŠs bien exporter autre chose que de l'asembleur, ex‚cuter autre
chose que ASM.TTP. On peut imaginer qu'un programme FORTH ait besoin
d'une image calcul‚e par POV:

	0 >export "F:\POV\image.pov"	\ envoit le script sur disque
	...
	ici se trouve le script de l'image
	>comp

	0 >exec "F:\POV\pov30_82.ttp"	\ calcule l'image
	"-iIMAGE.POV -oIMAGE.TGA +w100 +h100" \ en 100x100

	: image
		[var]
		0 >include "F:\POV\IMAGE.TGA"	\ l'inclut au programme!
	;

	Le mot image d‚posera alors l'adresse du fichier en RAM.