L'ASSEMBLEUR microPIUP

L'assembleur microPIUP est intégré à l'archive du simulateur.

L'option à utiliser est -ass et le nom du fichier source est donné en argument :

	java  -jar   microPIUP.jar   -ass   fichier_source 

Le fichier exécutable produit se trouve dans le même répertoire que le fichier source et a un nom constitué du radical du nom du fichier source complété par l'extension .iup.

Ainsi la commande

	java  -jar microPIUP.jar   -ass   mesTests/test1.src 

produit le fichier exécutable test1.iup dans le répertoire mesTests.

1 Fichier source

Le contenu d'un fichier source en langage d'assemblage est une suite de lignes.

Chaque ligne contient une directive, une instruction ou est réduite à un commentaire.

Un commentaire commence par // et se poursuit jusqu'à la fin de la ligne.

2 Lexicographie

Les noms des registres : r0, r1, ... , r15, les noms d'instructions, les noms associés aux conditions (instructions Bcc et Jcc) et les directives sont des mots clés c'est-à-dire qu'ils ne peuvent être utilisés comme identificateurs (étiquettes). Ces mots clés peuvent s'écrire en majuscules ou en minuscules. Il n'est toutefois pas possible de mélanger majuscules et minuscules dans un même mot : word est un mot-clé, WORD aussi mais Word est un identificateur.

Les chaines de caractères littérales s'écrivent entre "

Seules les constantes entières sont utilisables (il n'y a pas d'instruction sur les nombres réels) elles s'écrivent en décimal ou en hexadécimal avec les notations habituelles. Le processeur ne manipulant que des données d'au plus 16 bits, si la valeur de la constante ne peut être codée sur 16 bits (en complément à 2) un avertissement est produit sur l'erreur standard.

Les identificateurs ("étiquettes" ou constantes nommées) ont la syntaxe habituelle. Tout identificateur représentant un emplacement (identificateur placé comme étiquette d'une instruction ou d'une directive rsw, rsb, byte, word, string) ou une valeur entière peut être utilisé avant d'être défini. Un identificateur défini comme "alias" d'un registre doit être défini avant d'être utilisé. Un identificateur ne peut avoir plusieurs définitions.

Les commentaires débutent par // et se poursuivent jusqu'à la fin de la ligne.

3 Les expressions

L'assembleur permet l'utilisation d'opérateurs arithmétiques + - * / (division entière) et % (modulo).

Le symbole $ représente la valeur courante du compteur d'emplacement de l'assembleur au début de l'assemblage de la ligne. L'exemple suivant montre quelles sont les valeurs successives du compteur d'emplacement lors de l'assemblage :

// initialement il vaut zéro
		org		0x1000
// ici il vaut 0x1000
		word		$+20 // l'expression vaut  0x1020 
// ici le compteur d'emplacement vaut 0x1002
		start		debut
// ici il vaut toujours 0x1002
debut		stw		r1,@$-2  // l'expression vaut  0x1000 
// ici le compteur d'emplacement vaut 0x1006

Les expressions notées expression_entière et expression_d_adresse combinent la notation $ qui représente la valeur courante du compteur d'emplacement, des constantes entières et des identificateurs avec ces opérateurs et des parenthèses selon les règles habituelles. Elles ne se distinguent pas syntaxiquement mais, comme leurs noms l'indiquent, les premières représentent des nombres et les secondes des adresses.

Pour déterminer si une expression est une expression_entière ou une expression_d_adresse il faut utiliser récursivement les règles suivantes :

L'utilisation de chaînes de caractères ou de désignations de registres dans une expression arithmétique est interdite et provoque l'affichage d'un message d'erreur sur la sortie standard.

4 Les directives

start

              start	expression_d_adresse 

fixe l'adresse de la première instruction à exécuter.

Il y a au plus une directive start dans un texte. En son absence l'adresse de la première instruction est 0.

stackbase

              stackbase	expression_d_adresse

détermine l'adresse de la base de la pile : au chargement du module exécutable le registre SP est initialisé avec cette adresse qui sert de borne lors de la visualisation de la pile.

Il y a au plus une directive stackbase dans un texte. En son absence l'adresse de la base de la pile est 0x1000.

org

identificateur	org	expression_entière 
              	org	expression_entière 

La valeur de expression_entière constitue l'adresse de chargement de l'exécutable produit et sert à initialiser le compteur d'emplacement de l'assembleur, elle doit donc pouvoir être évaluée immédiatement.

Dans la première forme la valeur de l'expression est associée à identificateur .

Cette directive ne peut figurer qu'une fois dans un fichier source et ne peut être précédée que de directives equ. En l'absence de directive org l'adresse de chargement de l'exécutable est 0.

equ

identificateur	equ	expression_entière
identificateur	equ	expression_d_adresse
identificateur	equ	nom_de_registre_R

associe à identificateur l'expression ou le nom de registre figurant à droite du mot-clé : partout dans la suite du texte identificateur est remplacé par la valeur de l'expression ou par le nom du registre.

rsb

identificateur	rsb	expression_entière 
              	rsb	expression_entière 

réserve expression _entière octet(s) à partir de la valeur courante du compteur d'emplacement. L'expression expression_entière doit pouvoir être évaluée dès sa lecture (pas de référence en avant dans l'expression).

Dans la première forme la valeur associée à identificateur est la valeur courante du compteur d'emplacement (l'adresse du 1er octet réservé).

rsw

identificateur	rsw	expression_entière 
              	rsw	expression_entière 

réserve expression_entière mot(s) à partir de la valeur courante du compteur d'emplacement. L'expression expression_entière doit pouvoir être évaluée dès sa lecture (pas de référence en avant dans l'expression).

Dans la première forme la valeur associée à identificateur est la valeur courante du compteur d'emplacement (l'adresse du 1er mot réservé).

byte

identificateur	byte	expression_entière 
              	byte	expression_entière 

réserve un octet et l'initialise avec la valeur de expression_entière . Si cette valeur ne peut se coder sur un octet elle est tronquée et un message d'avertissement est affiché sur l'erreur standard.

Dans la première forme la valeur associée à identificateur est la valeur courante du compteur d'emplacement (l'adresse du 1er octet réservé).

word

identificateur	word	expression_entière 
              	word	expression_entière 

réserve un mot et l'initialise avec la valeur de expression_entière . Si cette valeur ne peut se coder sur un mot elle est tronquée et un message d'avertissement est affiché sur l'erreur standard.

Dans la première forme la valeur associée à identificateur est la valeur courante du compteur d'emplacement (l'adresse du 1er mot réservé).

string

identificateur	string	chaine_de_caractères
              	string	chaine_de_caractères

réserve le nombre d'octets nécessaires et initialise ces octets avec les codes ASCII des caractères de la chaîne. Un caractère NUL est toujours ajouté par l'assembleur en fin de chaîne. Dans la première forme la valeur associée à identificateur est la valeur courante du compteur d'emplacement (l'adresse du 1er octet réservé).

5 Les instructions

N.B. Les noms utilisés dans le document Description de la machine microPIUP pour présenter le jeu d'instructions servent de mots clés dans le langage d'assemblage.

De façon générale un identificateur peut être placé en début d'instruction, il sert alors d'étiquette à l'instruction et l'assembleur lui associe la valeur courante du compteur d'emplacement (l'adresse du premier mot de l'instruction).

instructions du groupe 1

identificateur	CODE		nom_de_registre , nom_de_registre , nom_de_registre 
              	CODE		nom_de_registre , nom_de_registre , nom_de_registre 

Les registres figurent dans la ligne dans le même ordre que dans le mot d'instruction.

instructions du groupe 2 (sauf ANI, ADI)

identificateur	CODE		nom_de_registre , nom_de_registre
              	CODE		nom_de_registre , nom_de_registre

Les registres figurent dans la ligne dans le même ordre que dans le mot d'instruction.

instructions ANI et ADI

identificateur	CODE		nom_de_registre , nom_de_registre , # expression
              	CODE		nom_de_registre , nom_de_registre , # expression

Les registres figurent dans la ligne dans le même ordre que dans le mot d'instruction. expression est une expression_entière ou une expression_d_adresse et sa valeur est codée dans le mot d'extension.

instructions du groupe 3

identificateur	CODE		nom_de_registre , spécification_d_adressage
              	CODE		nom_de_registre , spécification_d_adressage

instructions du groupe 4 (Jcc)

identificateur	Jcc		# expression_entière
              	Jcc		# expression_entière

le mnémonique de l'instruction est construit en concaténant J avec les deux lettres identifiant la condition (cf. Description de la machine microPIUP ).

La valeur du déplacement expression_entière est codée dans le mot d'extension.

instructions du groupe 5

identificateur	CODE		spécification_d_adressage
              	CODE		spécification_d_adressage

instructions du groupe 6

identificateur	CODE
              	CODE

instructions du groupe 7 (LDQ, ADQ)

identificateur	CODE		expression , nom_de_registre
              	CODE		expression , nom_de_registre

expression est une expression_entière ou une expression_d_adresse dont la valeur doit être comprise entre -128 .. et +127. Cette valeur est codée dans les bits 0 à 7 de l'instruction.

instructions du groupe 8 (Bcc)

identificateur	Bcc		expression_entière
              	Bcc		expression_entière

le mnémonique de l'instruction est construit en concaténant B avec les deux lettres identifiant la condition (cf. Description de la machine microPIUP).

La valeur du déplacement expression_entière doit être comprise entre -128 .. et +127 et est codée dans les bits 0 à 7 de l'instruction .

6 Modes d'adressage

A chaque mode d'adressage correspond une notation symbolique non ambiguë.

Adressage immédiat

	# expression_entière
	# expression_d_adresse

La valeur de l'expression constitue le contenu du mot d'extension.

Adressage de registre

	nom_de_registre

Adressage basé

	( nom_de_registre )

Adressage basé post-incrémenté

	( nom_de_registre  ) +

Adressage basé pré-décrémenté

	- ( nom_de_registre )

Adressage direct

	@ expression_entière
	@ expression_d_adresse

La valeur de l'expression constitue le contenu du mot d'extension.

Il est à noter qu'on peut utiliser une adresse quelconque sans disposer d'une étiquette sur l'emplacement correspondant.

Adressage indexé

	( nom_de_registre )expression_entière

La valeur de expression_entière constitue la valeur du déplacement.

Adressage indirect pré-indexé

	* ( nom_de_registre )expression_entière

La valeur de expression_entière constitue la valeur du déplacement.

7 Exemple

L'exemple ci-dessous est un programme calculant la factorielle d'un nombre, itérativement et sans se préoccuper des débordement ni de la validité du paramètre :

	org    256
	start  debut
// sommet de pile r15
// pour empiler on pre-decremente : la pile "monte" vers les  adresses basses
pile	equ	r15
// registre de liaison (adresse de retour) pour les appels de sous programmes r0
adRetour	equ	r0
// toute fonction retourne sa valeur dans r1
valRetour	equ	r1
// base locale
local	equ	r14
// codes des "primitives" systeme
exit	 equ    5
getline  equ    6
putline  equ    7
// int  fact(int n) 
// C'est du C, les parametres sont passes par valeur
n		equ	4
fact		stw	local,-(pile)	// sauvegarde du referentiel local
		stw	pile,local	// mise-a-jour du referentiel - pas indispensable ici
//	faire le dessin de la pile a ce point
// 	int resultat, k ;
resultat	equ	valRetour
k		equ	r2
// 	k = n;
	ldw		k,(local)n
//	resultat = k ;
	stw		k,resultat
//	k -- ;
	adq 		-1,k
//	while (k > 1){
	ldw 		r9,#1
while1	cmp	k,r9
		jle #endWhile1-$-2
//		resultat = resultat * k ;
			mul	resultat,k,resultat
//		k -- ;
			adq -1, k
		jmp #while1-$-2
//	}
//	return resultat ;
endWhile1	ldw	pile,local	// pas indispensable  ici
	ldw		local,(pile)+	// restauration du referentiel local
	rts
//}
// programme principal et variables "globales"
//	char donnee[20] ;
donnee	rsw	20	// 20 octets pour la variable donnee
//	int entier ;
entier		rsw	1	// 1 mot pour la variable entier
// debut
debut      ldw		pile,#2000	// initialisation du sommet de pile
	    ldw		local,pile	// referentiel local - pas  indispensable
//	donnee = lire()
//	    ldw		r0,#donnee
//	    trp		#getline
//	entier = aToInt(donnee) ;	// aToI()  est a definir
//	    ldw		r2,#donnee
//	    stw		r2,-(pile)
//	    jsr		@aToI
//	    ldw		r8,#2
//	    add		pile,r8,pile
//	    stw		valRetour,@entier
//	en attendant d'avoir defini aToI() : entier = 5 
	    ldw		valRetour,#5
	    stw		valRetour,@entier
//	fact(entier);
	    stw		valRetour,-(pile)
	    jsr 		@fact
	    ldw		r8,#2
	    add		pile,r8,pile
// le resultat est dans le registre valRetour, i.e. r1
// en attendant d'ecrire une conversion int -> texte : ecrire "le resultat est dans r1"
	    ldw		r0,#texte
	    trp		#putline
//fin
	    trp		#exit		//  retour au systeme
texte	   string	"le resultat est dans r1"
// int aToI(char *chaine) 
aToI	   rts

8 Format des fichiers exécutables produits par l'assembleur

Selon le cas, seuls les 4 ou 5 premiers caractères de chaque ligne d'un fichier exécutable sont interprétés par le chargeur. Le reste de la ligne constitue un commentaire (il est donc ignoré).

Les 4 premiers caractères de la première ligne d'un fichier exécutable sont des chiffres hexadécimaux qui représentent l'adresse de chargement du programme en mémoire.

Les 4 premiers caractères de la deuxième ligne sont des chiffres hexadécimaux qui représentent l'adresse de la première instruction à exécuter c'est-à-dire la valeur initiale du compteur ordinal.

Si le premier caractère de la troisième ligne est un S, les 4 caractères suivants sont des chiffres hexadécimaux qui représentent l'adresse de base de la pile, c' est-à-dire la valeur initiale du registre SP, sinon les 4 premiers caractères de la troisième ligne sont des chiffres hexadécimaux qui représentent le premier mot à charger en mémoire.

Les 4 premiers chiffres hexadécimaux des lignes suivantes représentent les mots qui doivent être rangés consécutivement en mémoire.