Introduction

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

Dans ce didacticiel, vous allez exécuter du code importé.

Le temps de lecture de ce didacticiel est estimé à 15 minutes si l'écriture basique du code, les sauts et les fonctions ont été abordés.

Mise en place

Pour commencer, créez le canevas de l'application dans le fichier exécutable bibliotheques.svm en utilisant ce code :

#!/usr/bin/env svm
DESCRIPTION
Libraries example
END
LOG
DEBUG "Libraries" STYLE "default"
PLUGIN "svmcom.so"
PROCESS "application"
	CODE "main" INLINE
		:debug BREAK
		:memory STR/source
		""":com.message 1
                   :shutdown
                :label l
                   :com.message 2
                   :return
                :label s
                   :com.message 3
                   :return
                """ -> &source
	END
END

Bibliothèques

Depuis une chaine

Observez le code fourni. La chaine de caractères définie dans le code a deux spécificités :

Modifiez le code pour obtenir :

#!/usr/bin/env svm
DESCRIPTION
Libraries example
END
LOG
DEBUG "Libraries" STYLE "default"
PLUGIN "svmcom.so"
PROCESS "application"
	CODE "main" INLINE
		:debug BREAK
		:memory STR/source, LIB/library
		""":com.message 1
                   :shutdown
                :label l
                   :com.message 2
                   :return
                :label s
                   :com.message 3
                   :return
                """ -> &source
		:library "lib" @&source -> &library
	END
END

Lancez l'application en mode débugueur. La fenêtre mémoire à la fin de l'exécution contient :

Libraries
Memory - K main - P application
AddressTypeValue
&0STR":com.message 1\n\t\t :shutdown\n\t\t:label l\n\t\t :com.message 2\n\t\t :return\n\t\t:label s\n\t\t :com.message 3\n\t\t :return\n\t\t"
&1LIB<lib:2>
AliasPointer
library&1*1
source&0*1
Address:
Display
Aliases
P
Focus
Back
Clear

La mémoire contient deux adresses. La première contient sans surprise la chaine avec le texte source.

La seconde est de type LIB (pour "library" en anglais) et contient le code compilé de la bibliothèque. La valeur est représentée par le nom de la bibliothèque (donné en premier argument de l'instruction :library) suivi d'un identifiant généré par la machine, le tout entre chevrons.

Depuis un fichier

Prenez le contenu de la chaine et mettez le à part dans un fichier non exécutable lib.svm, puis modifiez le code :

#!/usr/bin/env svm
DESCRIPTION
Libraries example
END
LOG
DEBUG "Libraries" STYLE "default"
PLUGIN "svmcom.so"
PROCESS "application"
	CODE "main" INLINE
		:debug BREAK
		:memory com.device/file, STR/source, LIB/library
		:com.open com.file < "lib.svm" -> &file
		:com.read @&file com.all -> &source
		:library "lib" @&source -> &library
		[ ] -> file
	END
END

Lancez l'application en mode débugueur. A la fin de l'exécution du code, vous devez obtenir sensiblement la même fenêtre mémoire :

Libraries
Memory - K main - P application
AddressTypeValue
&0com.device
&1STR"\t:com.message 1\n\t:shutdown\n:label l\n\t:com.message 2\n\t:return\n:label s\n\t:com.message 3\n\t:return\n"
&2LIB<lib:2>
AliasPointer
file&0*1
library&2*1
source&1*1
Address:
Display
Aliases
P
Focus
Back
Clear

Cet extrait de code permet de morceler l'application en plusieurs fichiers, ou d'importer du code écrit par d'autres personnes.

Utilisation de la bibliothèque

Maintenant que l'on a la bibliothèque enregistrée dans la mémoire, il est temps d'appeller le code via un saut ou un appel de fonction.

Revenez au fichier précédent, puis modifiez le code pour obtenir :

#!/usr/bin/env svm
DESCRIPTION
Libraries example
END
LOG
DEBUG "Libraries" STYLE "default"
PLUGIN "svmcom.so"
PROCESS "application"
	CODE "main" INLINE
		:debug BREAK
		:memory STR/source, LIB/library
		""":com.message 1
                   :shutdown
                :label l
                   :com.message 2
                   :return
                :label s
                   :com.message 3
                   :return
                """ -> &source
		:library "lib" @&source -> &library
		:call s P
	END
END

Puis lancez l'application :

./bibliotheques.svm
Boot error: Process application has invalid code: @(main, line 13) Label s is not defined in code main.

Et cela ne fonctionne pas ! En effet, l'appel vers l'étiquette "s" ne peut aboutir que si elle est définie dans le code de base "main" et non dans le code compilé "lib". Pour atteindre le code contenu dans "lib", il faudra un nouveau concept : les symboles.

Symboles

Utilisation

Modifiez le code :

#!/usr/bin/env svm
DESCRIPTION
Libraries example
END
LOG
DEBUG "Libraries" STYLE "default"
PLUGIN "svmcom.so"
PROCESS "application"
	CODE "main" INLINE
		:debug BREAK
		:memory STR/source, LIB/library
		""":com.message 1
                   :shutdown
                :label l
                   :com.message 2
                   :return
                :label s
                   :com.message 3
                   :return
                """ -> &source
		:library "lib" @&source -> &library
		:call $(@&library/"s") P
	END
END

Lancez l'application :

./bibliotheques.svm
### Simple Virtual Machine 1234 : PROCESS application | 2023-01-01 00:00:00 GMT ######################################################################
Kernel interrupted: @(main, line 13) Interruption FAILURE not handled: Symbol s is not defined in code lib.

Core dump:
Kernel:
State: I, transmit_interruption, interrupted @(main, line 13) Interruption FAILURE not handled: Symbol s is not defined in code lib.

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

Code at <main:1/4>:
     :debug BREAK       # <0> @(main, line 1)
     :memory STR/source , LIB/library   # <1> @(main, line 2)
     """:com.message 1\n\t\t   :shutdown\n\t\t:label l\n\t\t   :com.message 2\n\t\t   :return\n\t\t:label s\n\t\t   :com.message 3\n\t\t   :return\n\t\t""" -> &source  # <2> @(main, lines 3-11)
     :library "lib" @&source -> &library        # <3> @(main, line 12)
====== HERE ======
     :call $(@&library/"s") P   # <4> @(main, line 13)
==================
 Labels:
 Symbols:


Memory:
  &0: STR ":com.message 1\n\t\t   :shutdown\n\t\t:label l\n\t\t   :com.message 2\n\t\t   :return\n\t\t:label s\n\t\t   :com.message 3\n\t\t   :return\n\t\t"
  &1: LIB <lib:2>
 Aliases:
  library -> &1*1
  source -> &0*1
 Free space:



### Simple Virtual Machine 1234 : SYSTEM | 2023-01-01 00:00:00 GMT ###################################################################################
Process application interrupted: @(main, line 13) Interruption FAILURE not handled: Symbol s is not defined in code lib.

La cible de l'appel a été modifiée et contient maintenant une référence sur le code de la bibliothèque et une étiquette de la bibliothèque.

Cependant, les étiquettes comme "l" et "s" dans une bibliothèque ne peuvent pas être appellées depuis une instruction placée dans un autre code que cette bibliothèque.

Déclaration

Modifiez le code pour changer "s" :

#!/usr/bin/env svm
DESCRIPTION
Libraries example
END
LOG
DEBUG "Libraries" STYLE "default"
PLUGIN "svmcom.so"
PROCESS "application"
	CODE "main" INLINE
		:debug BREAK
		:memory STR/source, LIB/library
		""":com.message 1
                   :shutdown
                :label l
                   :com.message 2
                   :return
                :symbol s
                   :com.message 3
                   :return
                """ -> &source
		:library "lib" @&source -> &library
		:call $(@&library/"s") P
		:goto $(@&library/)
	END
END

Puis lancez l'application :

./bibliotheques.svm
3
1

Cette fois-ci, l'appel est bien réalisé. Le saut ajouté à la suite de l'appel fonctionne également, et exécute le code "lib" à partir de la première instruction.

Vous pouvez lancer l'application en mode débugueur. Lors de l'exécution de la fonction "s", les fenêtres du processeur et des codes ressemblent à :

Libraries
Processor - K main - P application
State:
Next instruction: <lib:2/5>
Current instruction: <lib:2/4>
Code
Current memory: &0*0
Allocated memory:
Defined aliases:
Local interruptions:
Cascaded local interruptions:
Flags:
Cascaded flags:
Return stack:
State:
Next instruction: <main:1/5>
Current instruction: <main:1/4>
Code
Current memory: &0*0
Allocated memory: &0*2
Defined aliases: library source
Local interruptions:
Cascaded local interruptions:
Flags:
Cascaded flags:
Global interruptions:
Waiting interruptions:
Code lib - K main - P application
:com.message 1
:shutdown
:label l

:com.message 2
:return
:symbol s

:com.message 3
:return
Auto-scroll to
Current
with above
Display
=Code main - K main - P application
:debug BREAK
:memory STR/source , LIB/library
""":com.message 1
		   :shutdown
		:label l
		   :com.message 2
		   :return
		:symbol s
		   :com.message 3
		   :return
		""" -> &source
:library "lib" @&source -> &library
:call $(@&library/"s") P
:goto $(@&library/)
Auto-scroll to
Current
with above
Display

Entre l'état du processeur et la pile de retour, vous retrouvez la référence aux deux codes "main" et "lib".

En jouant l'application instruction par instruction, vous pouvez constater comment l'exécution passe d'un code à l'autre.

Conclusion

Vous venez de voir comment intégrer du code depuis plusieurs sources au sein d'une application.

Cette capacité de la machine permet de constituer des applications en intégrant des modules écrits en langage machine.

Dans certaines circonstances, cela permet aussi d'exécuter du code généré par du code.