machine virtuelle du VPC-32V

machine virtuelle du VPC-32V

Licence

Ce document fait partie du projet VPC-32V et est fourni sous licence CC-NC-SA-BY V3.0

auteur: Jacques Deschênes
révision 1.0
Copyright: 2015,2016, Jacques Deschênes

Présentation

L'ordinateur VPC-32V possède un interpréteur BASIC qui exécute du bytecode sur une machine virtuelle à piles. Ce document décris cette machine virtuelle.

L'interpréteur vpcBASIC ecris en C commence par compiler le code source BASIC en bytecode pour cette machine virtuelle ensuite appelle la fonction
int StackVM(const uint8_t* prog_space)
qui est une fonction écrite en assembleur dans le fichier vm.S.
prog_space est la mémoire RAM allouée par l'interpréteur vpcBASIC où il compile le bytecode.

Architecture

Cette machine virtuelle utilise les 9 registres S0 à S8 du PIC32MX170F256B pour ses états internes ainsi que 2 piles. la première pile dstack est utilisée pour les arguments et la deuxième rstack est utilisée pour conserver les adresses de retours des sous-programmes ainsi que pour sauvegarder les registres step et limit lors de l'imbrication de boucles FOR. Les registres de la machine virtuelle sont les suivants:

les piles dstack et rstack peuvent contenir 256 éléments de 32 bits appellé cellule. Étant donné ces tailles limités il faut-être prudent dans l'utilisation des fonctions récursives.

codes machines

Cette table contient la description de chacun des codes machine (opcode) utilisés par la machine virtuelle. La notation état stack est une illustration de l'état de la pile dstack ou rstack avant et après l'exécution de cette instruction.

La majorité des opcodes correspondent directement à des commandes ou fonctions BASIC je ne décrirais donc pas celle-ci car ce serait redonnant avec la documentation du vpcBASIC.

opcodemnémoniquedescriptionétat stacks
0BYETermine l'exécution du programme et sortie de la machine virtuelle. La machine virtuelle retourne un code d'erreur ou 0 s'il n'y a pas d'erreur. Consulter les fichiers basic.c et basic.h pour plus d'information sur ces codes d'erreurs. La commande BASIC BYE appelle cet opcode.( -- )
1ABORTExécuté lorsque la machine virtuelle rencontre une erreur interne. Mais fin à l'exécution du programme avec sortie de stackVM avec un code d'erreur.( j*x -- j*x )
2LITEntier litéral 32 bits. L'entier suit l'opcode et est empilé au sommet de la pile.( -- n)
3WLITEntier litéral 16 bits. L'entier suit l'opcode et est empilé au sommet de la pile.( -- n)
4CLITEntier litéral 8 bits. L'entier suit l'opcode et est empilé au sommet de la pile.( -- n)
5BRABranchement relatif inconditionnel. L'offset de 16 bits signé suis le opcode. IP=IP+offset( -- )
6?BRABranchement relatif conditionnel à f<>0.L'offset de 16 bits signé suis le opcode. IP=IP+offset ( f -- )
7!Sauvegarde T dans une variable 32 bits. var=n( n adr -- )
8@Empile la variable entier 32 bits dont l'adresse est au sommet de la pile.( adr -- n )
9C!Sauvegarde une variable entier 8 bits. var#=c( c adr -- )
10C@Empile la variable entier 8 bits dont l'adresse est au sommet de la pile.( adr -- c )
11DROPJette l'élément au sommet de la pile dstack.( n -- )
12DUPClone le sommet de la pile dstack( n -- n n )
13SWAPInterchange les 2 éléments au sommet de dstack( n1 n2 -- n2 n1 )
14OVERCopie le 2ième élément de la pile dstack au sommet.( n1 n2 -- n1 n2 n1 )
15PICKCopie le nième élément de la pile dstack au sommet.( n1 n2...nx ... ox -- n1 n2 ... nx ... nx )
16INVERTnégation arithmétique du sommet de la pile.( n -- -n )
17+Addition( n1 n2 -- n1+n2 )
18-Soustraction( n1 n2 -- n1-n2 )
19*Multiplication entière( n1 n2 -- n1*n2 )
20/Division entière( n1 n2 -- n1/n2 )
21MODModulo( n1 n2 -- n1%n2 )
220<Si T<0 f=-1 sinon f=0( n1 n2 -- f )
230=Si T==0 f=-1 sinon f=0( n1 n2 -- f )
24&Fonction binaire ET.( n1 n2 -- n1&n2 )
25|Fonction binaire OU inclusif.( n1 n2 -- n1|n2 )
26^Fonction binaire OU exclusif.( n1 n2 -- n1^n2 )
27~Remplace l'entier au sommet de la pile par son complément à 1( n -- ~n )
28NOTnégation booléenne. Si f1 est faux alors f2=vrai sinon f2=faux.( f1 -- f2 )
29OROU booléen. Si f1 ou f2 est vrai alors f3=vrai sinon f3=faux.( f1 f2 -- f3 )
30ANDET booléen. Si f1 et f2 sont vrai alors f3=vrai sinon T=faux.( f1 f2 -- f3 )
31TICKSEmpile la valeur de la variable système systicks( -- u )
32SLEEPsuspend l'exécution du programme pour u millisecondes.( u -- )
33?DUPClone le sommet de la pile dstack si différent de zéro.( n -- 0 | n n )
341+Incrémente le sommet de la pile.( n -- n+1 )
351-Décrément le sommet de la pile( n -- n-1 )
36+!Incrémente la variable à l'adresse adr de la valeur n.( n adr -- )
37ROTRotation horaire des 3 éléments au sommet de dstack.( n1 n2 n3 -- n2 n3 n1 )
38-ROTRotation anti-horaire des 3 éléments au sommet de dstatck.( n1 n2 n3 -- n3 n1 n2 )
39MINConserve le plus petit de n1 et n2( n1 n2 -- n )
40MAXConserve le plus grand de n1 et n2( n1 n2 -- n )
41ABSRemplace l'entier n par sa valeur absolue.( n -- u )
42LSHIFTDécale vers la gauche l'entier n de u bits.( n u -- n )
43RSHIFTDécale vers la droite l'entier n de u bits.( n u -- n )
440BRABranchement relatif de 16 bits si n==0. Le déplacement suis l'opcode.( n -- )
45DCNTEmpile le nombre d'éléments sur dstack( -- u )
46=Compare n1 et n2 pour l'égalité( n1 n2 -- f )
47<>Compare n1 et n2, retourne vrai si différents.( n1 n2 -- f )
48<f=n1<n2( n1 n2 -- f )
49>f=n1>n2( n1 n2 -- f )
50<=f=n1<=n2( n1 n2 -- f )
51>=f=n1>=n2( n1 n2 -- f )
52FOR>RSauvegarde de limit et step sur rstack( R: -- limit step )
53R>FORRestaure limit et step à partir de rstack( limit step -- )
54FORInitialisation de limit et step pour la boucle FOR...NEXT( limit step -- )
55FOR?Compare n à limit pour dépassement. f=vrai si n>limit.( n -- f )
56FORNEXTIncrément la variable de contrôle de la boucle FOR...NEXT avec la valeur de step. L'adresse de la variable est au sommet de dstack.( adr -- )
57RANDOMIZEInitialize le générateur pseudo-hasard en utilisant systicks.( -- )
58RNDEmpile un entier pseudo-aléatoire entre 0 et MAXINT.( -- u )
59KEYAttend réception d'un caractère de la console.( -- c )
60KEY?Vérifie s'il y a un caractère dans la file du clavier console. Retourne le caractère disponible ou 0.( -- 0|c )
61EMITEnvoie à la console le caractère c.( c -- )
62PSTREnvoie à la console la chaîne imbriquée dans le code à la suite de ce opcode.( -- )
63CREnvoie à la console une commande de retour à la ligne( -- )
64.Imprime sur la console l'entier n( n -- )
65TYPEImprime sur la console la chaîne située à l'adresse adr( adr -- )
66SPACESImprime sur la console n espaces.( n -- )
67SOUNDFait entendre une tonalité de fréquence u1 et de durée u2 millisecondes.( u1 u2 -- )
68BEEPFait entendre une tonalitée brève de 1000 hertz.( -- )
69PLAYJoue une mélodie dont le code est à l'adresse adr. Voir la commande BASIC PLAY.( adr -- )
70CLSVide l'écran de la console et positionne le curseur texte dans le coin supérieur gauche.( -- )
71UBOUNDEmpile la grandeur de la variable tableau à l'adresse adr( adr -- u )
72LC!Sauvegarde la variable locale dont la position suit cet opcode. Les variables locales sont conservées sur dstack. L'opcode est suivit de la position de la variable relativement au pointeur frame.( n -- )
73LC@Empile la variable locale dont la position suit cet opcode. Les variables locales sont conservées sur dstack. L'opcode est suivit de la position de la variable relativement au pointeur frame.( -- n )
74LCADREmpile l'adresse absolue d'une variable locale dont l'offset suit cet opcode.( -- adr )
75FRAMESauvegarde frame sur rstack et l'initialise avec la nouvelle valeur. Un octet suit le opcode pour indiquer le nombre de cellules qui ont été réservées sur dstack pour les arguments de la fonction. frame pointe le premier argument. Cet opcode précède un CALL(R: -- frame )
76CALLAppel la sous-routine à l'adresse adr. Sauvegarde ip sur rstack et initialise ip avec adr.( adr -- )
(R: -- ip)
77LEAVESortie de sous-routine. Transfert frame dans dp pour libérer les arguments et variables locales j*nq ui étaient utilisées par cette sous-routine. Dépile rstack dans ip et ensuite dans frame ( j*n -- )
(R: frame ip -- )
78LOCALCet opcode viens à la suite d'un CALL. Ajuste dp pour réserver sur dstack l'espace pour les variables locales. Le nombre de cellules à réserver est un octet qui suit l'opcode. j*n représente les cellules supplémentaires réservées sur dstack. ( -- j*n )
79TRACEActivation de l'outil de débogage TRACE. Voir la discription plus bas. n indique le mode de débogage.( n -- )
80$ADREmpile l'adresse de la chaîne imbriquée dans le code à la suite de cet opcode. Après exécution de cet instruction ip pointe l'opcode qui suit immédiatement la chaîne.( -- adr )
81LENRetourne la longueur de la chaîne adr.( adr -- u )
82READLNLecture d'une ligne à partir de la console. adr est l'adresse du tampon qui doit recevoir les caractères. n1 est la longueur du tampon. n2 est la longueur de la chaîne lue. ( adr n1 -- adr n2 )
83VALConvertie la chaîne en nombre.( adr -- n )
84VALLOCAlloue n octets dans l'espace réservé aux variables BASIC. adr est l'adresse de l'espace allouée( -- adr )
85$ALLOCAlloue une chaîne dynamique de longueur n. adr est l'adresse de l'espace alloué.( -- adr )
86$FREELibère une chaîne allouée dynamiquement. adr est l'adresse retournée par $ALLOC( adr -- )
87$FREENOTREFLibère la chaîne adr seulement si elle n'est pas référencée. ( adr -- )
88$CPYCopie la chaîne src dans dest.( src dest -- dest )
89CURLINERetourne la ligne sur laquelle se trouve le curseur texte.( -- n )
90CURCOLRetourne la colonne sur laquelle se trouve le curseur texte.( -- n )
91LOCATEPosistion le curseur texte à ligne, col.( ligne col -- )
92BTESTRetourne la valeur du bit b de l'entier n( n b -- 0|1 )
93SETTMRInitialize la minuterie à u millisecondes.( u -- )
94TIMEOUTVérifie si la minuterie est expirée.( -- f )
95INVERTVIDSélectionne le mode vidéo. 0 blanc/noir, 1 noir/blanc( 0|1 -- )
96SCRLDNGlisse l'écran console d'une ligne texte vers le bas, laissant la ligne du haut vide.( -- )
97SCRLUPGlisse l'écan console d'une ligne vers le haut, laissant la ligne du bas vide.( -- )
98INSERLNInsère une ligne vide là où le curseur texte se trouve. Positionne le curseur au début de la ligne.( -- )
99PGETObtient la valeur du pixel du moniteur VGA aux coordonnées {x,y}.( x y -- 0|1 )
100PSETFixe l'état du pixel du moniteur VGA aux coordonées {x,y} à l'état p.( x y p -- )
101PXORInverse l'état du pixel du moniteur VGA aux coordonnées {x,y}.( x y -- )
102LINETrace une ligne entre les points {x0,y0} et {x1,y1}.( x0 y0 x1 y1 -- )
103RECTDesssine un rectangle, {x,y} coin supérieur gauche. w largeur, h hauteur( x y w h -- )
104BOXDessine une boite, {x,y} coin supérieur gauche. w largeur, h hauteur( -- )
105CIRCLEDessine un cercle de centre {x,y} et de rayon r( x y r -- )
106ELLIPSEDessine une ellipse circonscrite dans le rectangle.( x0 y0 x1 y1 -- )
107POLYGONDessine un polygon. Voir la commande BASIC correspondante.( adr n -- )
108FILLRemplie une figure fermée. Voir la commande BASIC correspondante.( x y -- )
109SPRITEDessine un sprite. Voir la commande BASIC correspondante.( adr w h -- )
110VGACLSVide l'écran du moniteur VGA.( -- )
111SRCLEAR Voir la commande BASIC correspondante.( adr size -- )
112SRREAD Voir la commande BASIC correspondante.( adr_ram adr_v size -- )
113SRWRITE Voir la commande BASIC correspondante.( adr_ram adr_v size -- )
114SAVESCR Voir la commande BASIC correspondante.( adr -- )
115RESTSCR Voir la commande BASIC correspondante.( adr -- )
116SRLOAD Voir la commande BASIC correspondante.( addr_ram char* -- size )
117SRSAVE Voir la commande BASIC correspondante.( addr_ram char* size -- exit_code )
118MDIV Voir la commande BASIC correspondante.( n1 n2 n3 -- n1*n2/n3 )
119STR$Correspond à la fonction BASIC du même nom. n est l'entier à représenter en chaîne. pad est un espace de travail fourni par le compilateur et adr est un pointeur sur la chaîne allouée dynamiquement qui contient la représentation texte de l'entier.( n pad -- adr )
120ASCCorrespond à la fonction BASIC du même nom. adr est un pointeur sur une chaîne dont la valeur ASCII du premier caractère est retournée n.( adr -- n )
121CHR$correspond à la commande BASIC du même nom. n est un entier dont les 8 bits les moins significatifs sont le caractère stocké dans la chaîne adr allouée dynamiquement.( n -- adr )
122DATE$Voir la fonction BASIC. adr est le pointeur de la chaîne date allouée dynamiquement.( -- adr )
123TIME$Voir la fonction BASIC. adr est le pointeur de la chaîne heure allouée dynamiquement.( -- adr )
124APPEND$Voir la fonction BASIC. s1 est le pointeur de la première chaîne. s2 est le pointeur de la chaîne attachée à la fin de s1. s3 est le pointer vers la chaîne résultante allouée dynamiquement.( s1 s2 -- s3 )
125INSERT$Voir la fonction BASIC. s1 est le pointeur de la chaîne cible. s2 est le pointeur de la chaîne à insérer dans s1 et pos est la position d'insertion. s3 est le pointeur vers la chaîne résutante allouée dynamiquement.( s1 s2 pos -- s3 )
126LEFT$Voir la fonction BASIC. s1 est la chaîne originale. n est le nombre de caractères à conserver au début de s1. s2 est la chaîne allouée dynamiquement correspondant aux n premiers caractères de s1( s1 n -- s2 )
127MID$Voir la fonction BASIC. retourne les n1 caractères de s1 à partir de la position n1.( s1 n1 n2 -- s2 )
128PREPEND$Voir la fonction BASIC. Attache s2 au début de s1.( s1 s2 -- s3 )
129RIGHT$Voir la fonction BASIC. Retourne les n derniers caractères de s1.( s1 n -- s2 )
130SUBST$Voir la fonction BASIC. Substitution de s2 dans s1 à la position n.( s1 s2 n -- )
131INSTRVoir la fonction BASIC. Quel est la position de s2 dans s1?( n1 s1 s2 -- n2 )
132$CMPComparaison des chaînes s1 et s2. Si s1<s1==s2 retourne 0. Si s1>s2 retourne 1.( s1 s2 -- -1|0|1 )
133UCASE$Voir la fonction BASIC. ( s1 -- s2 )
134LCASE$Voir la fonction BASIC. ( s1 -- s2 )
135STR!Assigne la chaîne str à la variable var( str var -- )
136HEX$Voir la fonction BASIC. n est le nombre dont on veut obtenir la représentation hexadécimale. pad est un espace de travail fournie par le compilateur et adr est la chaîne allouée représentant le nombre hexadécimal.( n pad -- adr )
137DP0Empile la valeur du pointeur dp lorsque la pile est vide.( -- adr )
138CLOSEVoir la commande BASIC CLOSE(). n est le numéro du fichier à fermer.( n -- )
139CLOSEALLFerme tous les fichiers ouvert.( -- )
140EOFVoir commande BASIC. n est le numéro du fichier à vérifier.( n -- )
141OPENVoir commande BASIC. s1 est le pointer vers le nom du fichier. u1 est le mode et u2 est numéro à assigner à ce fichier.( s1 u1 u2 -- )
142EXISTVoir commande BASIC. s1 pointeur vers le nom du fichier. Retourne 0 si le fichier n'existe pas et 1 s'il existe.( s1 -- 0|1 )
143SEEKVoir commande BASIC. u1 numéro du fichier. n1 nouvelle position dans le fichier. ( u1 n1 -- )
144FGETCVoir commande BASIC. u1 numéro du fichier. c caractère lu.( u1 -- n1 )
145FPUTCVoir commande BASIC. u1 numéro du fichier. c caractère à écrire.( u1 c -- )
146WRITE_FIELDÉcris une chaîne dans caractères dans un fichier. u1 est le numéro du fichier déjà ouvert. s est un pointeur vers la chaîne à écrire dans le fichier.( u1 s -- )
147READ_FIELDLit une chaîne de caractères d'un fichier. une chaîne se termine par une fin de ligne ou une virgule si elle n'est pas entre guillemets.u1 est le numéro d'un fichier déjà ouvert. s est un pointeur vers la chaîne lue. L'espace pour cette chaîne est allouée dynamiquement.( u1 -- s )
148FP>$Convertie un nombre en virgule flottante en une chaîne le représentant. fp est le nombre et s est un pointeur vers la chaîne créée. L'espace pour cette chaîne est allouvée dynamiquement.( fp -- s )
149$>FPConvertie une chaîne en valeur numérique. s est une pointeur vers la chaîne à convertir. fp est le nombre résultant.( s -- fp )
150-FPNégation arithmétique d'un nombre en virgule flottante. n1 est le nombre à inverser. n2 est le résultat.( n1 -- n2 )
151FP>INTConversion d'un nombre en virgule flottante en entier. fp est le nombre à convertir. n est le résultat.( fp -- n )
152INT>FPConversion d'un entier en nombre à virgule flottante. n est l'entier à convertir. fp et le résultat.( n -- fp )
153F+Addition en virgule flottante. fp3=fp1+fp2.( fp1 fp2 -- fp3 )
154F-Soustraction en virgule flottante. fp3=fp1-fp2.( fp1 fp2 -- fp3 )
155F*Multiplication en virgule flottante. fp3=fp1*fp2( fp1 fp2 -- fp3 )
156F/Division en virgule flottante. fp3=fp1/fp2.( fp1 fp2 -- fp3 )
157SINUSFonction trigonométrique sinus(fp1). fp1 est l'angle en radian. fp2 est le résultat.( fp1 -- fp2 )
158COSFonction trignonométrique fp2=cosinus(fp1). fp1 est en radians.( fp1 -- fp2 )
159TANFonction trigonométrique fp2=tangeante(fp1).( fp1 -- fp2 )
160ATANFonction trigonométrique inverse fp2=arctageante(fp1). Le résultat est en radians.( fp1 -- fp2 )
161ACOSFonction trigonométrique inverse fp2=arccosinus(fp1). Le résultat est en radians.( fp1 -- fp2 )
162ASINEFonction trigonométrique inverse fp2=arcsinus(fp1). Le résultat est en radians.( fp1 -- fp2 )
163SQRTFonction racine carrée. fp2=sqrt(fp2).( fp1 -- fp2 )
164EXPFonction exponentielle. fp2=e^fp1( fp1 -- fp2 )
165POWERFonction puissance. fp3=fp1^pf2.( fp1 fp2 -- fp3 )
166LOGNFonction logarithme naturel. fp2=ln(fp1).( fp1 -- fp2 )
167LOG10Fonction logarithme de base 10. fp2=log10(fp1)( fp1 -- fp2 )
168FABSFonction valeur absolue d'un nombre en virgule flottante. fp2=abs(fp1).( fp1 -- fp2 )
169FLOORArrondi vers l'infini négatif d'un nombre en virgule flottante. fp2=floor(fp1)( fp1 -- fp2 )
170CEILArrondi vers l'infini positif d'un nombre en virgule flottante. fp2=ceil(fp1).( fp1 -- fp2 )
171FMODFonction qui retourne le modulo de fp3=fp1%pf2( fp1 fp2 -- fp3 )
172F.Imprime à l'écran de la console un nombre en virgule flottante.( fp -- )
173FMINRetourne le plus petit de 2 nombres en virgule flottante.( fp1 fp2 -- fpmin )
174FMAXRetourne le plus grand de 2 nombres en virgule flottantes.( fp1 pf2 -- fpmax )
175CONChange de console. Identifiant de la nouvelle console.( n -- )
176ENVRetourne la valeur d'une variable d'environnement. s1 est un pointeur vers le nom de la variable. s2 est un pointeur vers la valeur de la variable.( s1 -- s2 )

Outil de débogage TRACE

La commande TRACE peut-être placée n'importe où à l'interieur d'un programme aussi bien pour démarrer le traçage que pour l 'arrêter par exemple si on sait que le problème est a un endroit précis du code source on peut encadré ce bloc d'instruction.


	trace(1)
	bloc d'instruction à déboguer
	trace(0)
	

Puisqu'une image vaux mille mots voici une démonstration de l'utilisation de trace en mode pas à pas.

Les informations affichées sont les suivantes:


INDEX