Introduction

Ce didacticiel est destiné aux nouveaux utilisateurs de la Simple Virtual Machine.

Dans ce didacticiel, vous allez écrire le code d'une application SVM simple et analyser son exécution.

Le temps de lecture de ce didacticiel est estimé à 20 minutes si le lancement d'une application avec la machine virtuelle est déjà maîtrisé.

Mise en place

Le texte qui définit une application pour la machine virtuelle contient :

  1. différentes configurations globales à l'application,
  2. les options et arguments acceptés en ligne de commande,
  3. le code de l'application.

Pour ce didacticiel, nous allons nous focaliser sur le code. Ainsi, nous allons fournir le canevas de l'application.

Ouvrez un fichier texte que nous appellerons hello_world.svm et copiez/collez ce contenu à l'intérieur du fichier :

#!/usr/bin/env svm
DESCRIPTION
A first application!
END
LOG
DEBUG "First" STYLE "default"
PLUGIN "svmcom.so"
OPTION -w STR who
PROCESS "application"
	CODE "main" INLINE
	END
	MEMORY who
END

Pour terminer la mise en place, vous pouvez rendre ce fichier exécutable :

chmod u+x hello_world.svm

Une application en une ligne !

Nous n'allons pas sacrifier la tradition : notre première application sera un traditionnel "Hello world!".

Pour afficher un message sur le terminal, nous pouvons utiliser l'instruction :com.message fournie avec l'installation de la machine virtuelle.

Une instruction s'écrit toujours :

  1. en commençant par le caractère deux-points puis en indiquant le nom de l'instruction,
  2. ensuite viennent les paramètres de l'instruction, séparés par une espace ou une tabulation,
  3. pour terminer l'instruction, il faut placer un retour à la ligne.

Il ne peut donc jamais y avoir plus d'une instruction par ligne !

Ici, le paramètre est une seule chaine de caractères, indiquée par le texte entre deux double-quotes : "Hello world!".

Le code de l'application s'insère dans le fichier sur des lignes dédiées, placées entre la ligne finissant par INLINE et le END qui suit :

#!/usr/bin/env svm
DESCRIPTION
A first application!
END
LOG
DEBUG "First" STYLE "default"
PLUGIN "svmcom.so"
OPTION -w STR who
PROCESS "application"
	CODE "main" INLINE
		:com.message "Hello world!"
	END
	MEMORY who
END

L'invocation de l'application se fait normalement :

./hello_world.svm

Et le résultat est sans surprise :

Hello world!

Utilisation d'une valeur passée en option

On commence par coder !

Une application qui renvoie une valeur statique, c'est un premier pas. Maintenant, passons à la vitesse supérieure : utilisons une valeur placée sur la ligne de commande !

Dans le fichier de l'application, la ligne commençant par OPTION indique à la machine virtuelle que l'option -w est autorisée et qu'elle accepte un argument qui pourra être lu avec le nom who.

Pour cela, remplacez le mot world par un accès à who en ajoutant devant les symboles @& pour indiquer une lecture de la valeur :

#!/usr/bin/env svm
DESCRIPTION
A first application!
END
LOG
DEBUG "First" STYLE "default"
PLUGIN "svmcom.so"
OPTION -w STR who
PROCESS "application"
	CODE "main" INLINE
		:com.message "Hello " @&who "!"
	END
	MEMORY who
END

Il fallait également fermer les deux chaînes de caractères entourant la lecture de la valeur, pour s'assurer que le code inséré ne soit pas considéré par la machine comme une donnée chaine de caractères.

Et maintenant, on teste

Vous pouvez lancer l'application :

./hello_world.svm -w SVM

Et observez le résultat. La valeur passée sur la ligne de commande a bien été affichée par l'application :

Hello SVM!

Essayez avec d'autres valeurs pour bien valider que la valeur en ligne de commande est prise en compte par l'application.

Une amélioration de l'application

Enfin, essayez sans mettre l'option -w :

./hello_world.svm
### Simple Virtual Machine 1234 : PROCESS application | 2023-01-01 00:00:00 GMT ######################################################################
Kernel interrupted: @(main, line 1) Interruption MEMORY not handled: Read to non initialised address &0.

Core dump:
Kernel:
State: I, transmit_interruption, interrupted @(main, line 1) Interruption MEMORY not handled: Read to non initialised address &0.

Processor:
 State:
   Next instruction: <main:1/1> (Current one: <main:1/0>)
   Current memory  : &0*0
   Allocated memory:
   Aliases         :
   Flags           :
   Cascaded flags  :
   Local interruption handlers:
   Cascaded local interruption handlers:
 Saved states:
 Global interruption handlers:

Code at <main:1/0>:
====== HERE ======
     :com.message "Hello " @&who "!"    # <0> @(main, line 1)
==================
 Labels:
 Symbols:


Memory:
  &0: STR
 Aliases:
  who -> &0*1
 Free space:



### Simple Virtual Machine 1234 : SYSTEM | 2023-01-01 00:00:00 GMT ###################################################################################
Process application interrupted: @(main, line 1) Interruption MEMORY not handled: Read to non initialised address &0.


Ouch ! Cela n'était pas vraiment attendu. Il s'agit d'une erreur levée par la machine en exécutant l'application, mais non gérée par l'application. Quand cela se produit, la machine affiche l'état dans lequel l'erreur s'est produite pour aider à comprendre d'où peut provenir l'erreur.

Ici, l'erreur indique que la lecture de la valeur a échouée, car il n'y a pas de valeur à l'adresse &0. Cela se produit précisément quand l'option n'est pas donnée.

Il existe plusieurs stratégies pour résoudre cette situation, mais la plus simple reste de fournir une valeur par défaut quand l'option n'est pas fournie.

Ajoutez ces quelques lignes de code (vous pouvez changer la valeur par défaut si vous le voulez) :

#!/usr/bin/env svm
DESCRIPTION
A first application!
END
LOG
DEBUG "First" STYLE "default"
PLUGIN "svmcom.so"
OPTION -w STR who
PROCESS "application"
	CODE "main" INLINE
		:goto has_value :when &who INITIALISED
		"world" -> &who
	:label has_value
		:com.message "Hello " @&who "!"
	END
	MEMORY who
END

Lancez l'application avec et sans option -w. L'exécution se passe comme attendu maintenant :

./hello_world.svm -w SVM
Hello SVM!

./hello_world.svm
Hello world!

Exécution dans le débugueur

Pour bien visualiser l'exécution de l'application, rien de tel que la lancer dans le débugueur.

Avant de lancer l'application avec le débugueur, il faut ajouter un point d'arrêt :debug BREAK au début du code :

#!/usr/bin/env svm
DESCRIPTION
A first application!
END
LOG
DEBUG "First" STYLE "default"
PLUGIN "svmcom.so"
OPTION -w STR who
PROCESS "application"
	CODE "main" INLINE
		:debug BREAK
		:goto has_value :when &who INITIALISED
		"world" -> &who
	:label has_value
		:com.message "Hello " @&who "!"
	END
	MEMORY who
END

Comme vu dans le didacticiel numéro 2, lancez l'application dans le débugueur :

./hello_world.svm -d 8080 -w SVM

Une fois connecté au débugueur, suivez les mêmes étapes que dans le didacticiel numéro 2 pour afficher le processeur, le code et la mémoire de l'application :

Recommencez l'opération en enlevant l'option, et observez les différences sur la mémoire et les instructions exécutées :

./hello_world.svm -d 8080

Dans les deux cas, les instructions exécutées ne sont pas identiques et s'adaptent aux données qui leur sont présentées.

La succession des instructions exécutées s'appelle un flot d'instructions.

Ce flot d'instructions est dirigé par le processeur :

Conclusion

Vous venez de voir en écrivant une application simple comment s'organise l'exécution d'une application pour la machine virtuelle.

Grâce à une application simple, les concepts d'instruction et de flot d'instructions ont été acquis.

Pour la première fois, un élément vu à travers le débugueur est pris en flagrant délit : il s'agit du processeur, qui orchestre l'exécution du code dans la machine virtuelle.