Spécifications de la machine alien virtuelle (VAM)

Description

La machine alien virtuelle (VAM pour Virtual Alien Machine) s'apparente à un pseudo assembleur x86 simplifié.

Organisation mémoire

Le système semble disposer d'un espace mémoire composé de 2 segments contigus, chacun de taille 0x10000 et initialisés avec des octets 0x00 :

Il ne semble y avoir aucun mécanisme de protection de l'espace mémoire.

Les adresses sont sur 32 bits (4 octets).

Les entiers manipulés sont soit sur 8 bits (1 octet) soit sur 32 bits (4 octets en little endian).

Registres

Il y a 8 variables fixes ou registres 32 bits (4 octets) :

Jeu d'instructions

Le jeu d'instruction de la VAM est à taille variable. Sauf cas particulier décrit dans cette section (appel ou retour de fonction, saut conditionnel...), à chaque cycle le pointeur d'instruction P pointe au début d'une instruction i. L'instruction i est lue entièrement avant d'être exécutée ; ceci implique que le pointeur d'instruction P est incrémenté (a minima de 1 octet, mais le plus souvent d'autant d'octets que d'opérandes) pour pointer sur l'instruction suivante avant que l'instruction i ne soit exécutée. Attention également, dans certains cas (explicités également) les opérandes peuvent être de taille variable

Nous avons identifié les instructions / opérations suivantes :

AssembleurInstructionDescription
#NOPopération nulle
?gets()réserve U octets sur la pile (S = S - U) ; lit les caractères sur l'entrée standard et les copie sur la pile à l'adresse stockée dans S.
@puts()affiche la chaîne de caractères (jusqu'au caractère terminal \0) présente à l'adresse stockée dans M.
+ Rx RyADD Rx,Ryregistre Rx = valeur du registre Rx + valeur du registre Ry.
- Rx RySUB Rx,Ryregistre Rx = valeur du registre Rx - valeur du registre Ry.
* Rx RyMUL Rx,Ryregistre Rx = valeur du registre Rx * valeur du registre Ry.
& Rx RyAND Rx,Ryregistre Rx = ET LOGIQUE entre la valeur du registre Rx et la valeur du registre Ry.
| Rx RyOR Rx,Ryregistre Rx = OU LOGIQUE entre la valeur du registre Rx et la valeur du registre Ry.
^ Rx RyXOR Rx,Ryregistre Rx = OU EXCLUSIF entre la valeur du registre Rx et la valeur du registre Ry.
: Rx RyMOV Rx,Ryregistre Rx = valeur du registre Ry.
= Rx <value>MOV Rx,valuecopie la valeur 32 bits value dans le registre Rx.
< RxPOP Rxcopie la valeur sur la pile pointée par S dans le registre Rx ; le pointeur de pile est mis à jour (S = S + 4).
> RxPUSH Rxle pointeur de pile est mis à jour (S = S - 4) ; copie la valeur du registre Rx sur la pile pointée par S.
( <n> <fname>CALL <fname>appelle la fonction ayant pour nom fname ; n (entier sur 8 bits) correspondant au nombre de caractères du nom de la fonction (cf. section suivante).
)RETretour de fonction (cf. section suivante).
! <shift>JNZ <shift> si M != 0, le programme continue en P = P + 1 + shift (entier 32 bits signé en little endian), sinon le programme continue en P = P + 5.
$ <size> <data>PUSH <data>S = S - size ; copie les size (entier 32 bits en little endian) octets suivants sur la pile ; le programme continue en P = P + 5 + size.
.ENDfin du programme

Appels de fonctions

Le système supporte l'appel de fonction. Celui-ci est déclenché par le mnémnomique CALL décrit dans le tableau ci-dessus. Cela déclenche les traitements suivants :
  1. le système recherche, dans l'espace mémoire, l'adresse a de la fonction ayant pour nom fname.
  2. le système copie sur la pile l'adresse de l'instruction suivante : (S = S - 4 ; [S] = P + 2 + n) (pour rappel, n correspond au nombre de caractères du nom de la fonction).
  3. le programme continue en P = a.
Le retour d'une fonction est déclenché par le mnémonique RET, avec les traitements suivants :
  1. P = adresse présente sur la pile pointée par S ; S = S + 4.
  2. le programme continue en P.

Une fonction est définie par : { <n> <fname> } <code>n (entier sur 8 bits) donne le nombre de caractères du nom fname de la fonction. n et fname sont encadrés par des accolades.

Chargement d'un programme et démarrage

Lors de son chargement, un programme est entièrement copié en mémoire à partir de l'adresse 0x10000.

Ensuite, le système recherche une fonction main dans la mémoire, et démarre son execution à celle-ci.