Ce didacticiel est destiné aux nouveaux utilisateurs de la Simple Virtual Machine.
Dans ce didacticiel, vous allez marquer la pile de retour du processeur et agir en conséquence.
Le temps de lecture de ce didacticiel est estimé à 15 minutes si les fonctions ont été abordées.
Pour commencer, créez le canevas de l'application dans le fichier exécutable drapeaux.svm en utilisant ce code :
#!/usr/bin/env svm
DESCRIPTION
Flags example
END
LOG
DEBUG "Flags" STYLE "default"
PLUGIN "svmcom.so"
PLUGIN "svmint.so"
OPTION -i INT nb
PROCESS "application"
CODE "main" INLINE
:interruption CASCADE NUMERIC recover
:memory (PTR, INT)/parameters
@&nb -> (parameters/1)
:call compute parameters
:com.message @&nb ": " @(parameters/1)
:shutdown
# function compute PTR (internal), INT (input/output) nb
:label compute
:memory BLN -> &P
:int.div 1000 @(P/1) -> (P/1)
:int.cmp @(P/1) < 100 -> &@&P
:call sub_compute P :when @&@&P TRUE
:return
:label sub_compute
:int.div 100 @(P/1) -> (P/1)
:return
:label recover
1 -> (P/1)
:return
END
MEMORY nb
END
Commencez par jouer avec l'application en l'exécutant avec diverses valeurs pour l'option -i :
./drapeaux.svm -i 0
0: 100
./drapeaux.svm -i 1
1: 1000
./drapeaux.svm -i 2
2: 500
./drapeaux.svm -i 3
3: 333
./drapeaux.svm -i 100
100: 10
./drapeaux.svm -i 500
500: 50
./drapeaux.svm -i 1000
1000: 100
./drapeaux.svm -i 10000
10000: 1
Ajoutez un point d'arrêt dans le gestionnaire d'interruption :
#!/usr/bin/env svm
DESCRIPTION
Flags example
END
LOG
DEBUG "Flags" STYLE "default"
PLUGIN "svmcom.so"
PLUGIN "svmint.so"
OPTION -i INT nb
PROCESS "application"
CODE "main" INLINE
:interruption CASCADE NUMERIC recover
:memory (PTR, INT)/parameters
@&nb -> (parameters/1)
:call compute parameters
:com.message @&nb ": " @(parameters/1)
:shutdown
# function compute PTR (internal), INT (input/output) nb
:label compute
:memory BLN -> &P
:int.div 1000 @(P/1) -> (P/1)
:int.cmp @(P/1) < 100 -> &@&P
:call sub_compute P :when @&@&P TRUE
:return
:label sub_compute
:int.div 100 @(P/1) -> (P/1)
:return
:label recover
:debug BREAK "recover"
1 -> (P/1)
:return
END
MEMORY nb
END
Puis relancez l'application en mode débugueur avec les mêmes valeurs. L'application atteint le point d'arrêt pour les valeurs 0 depuis la fonction "compute" et 10000 depuis la fonction "sub_compute".
Modifiez le code pour obtenir :
#!/usr/bin/env svm
DESCRIPTION
Flags example
END
LOG
DEBUG "Flags" STYLE "default"
PLUGIN "svmcom.so"
PLUGIN "svmint.so"
OPTION -i INT nb
PROCESS "application"
CODE "main" INLINE
:interruption CASCADE NUMERIC recover
:memory (PTR, INT)/parameters
@&nb -> (parameters/1)
:call compute parameters
:com.message @&nb ": " @(parameters/1)
:shutdown
# function compute PTR (internal), INT (input/output) nb
:label compute
:flag "compute"
:memory BLN -> &P
:int.div 1000 @(P/1) -> (P/1)
:int.cmp @(P/1) < 100 -> &@&P
:call sub_compute P :when @&@&P TRUE
:return
:label sub_compute
:int.div 100 @(P/1) -> (P/1)
:return
:label recover
:debug BREAK "recover"
1 -> (P/1)
:return
END
MEMORY nb
END
Puis relancez en mode débugueur avec la valeur 0. Lorsque le point d'arrêt est atteint, la fenêtre du processeur doit ressembler à :
Dans la pile de retour, le premier niveau de retour contient bien le drapeau "compute".
Modifiez maintenant le code :
#!/usr/bin/env svm
DESCRIPTION
Flags example
END
LOG
DEBUG "Flags" STYLE "default"
PLUGIN "svmcom.so"
PLUGIN "svmint.so"
OPTION -i INT nb
PROCESS "application"
CODE "main" INLINE
:interruption CASCADE NUMERIC recover
:memory (PTR, INT)/parameters
@&nb -> (parameters/1)
:call compute parameters
:com.message @&nb ": " @(parameters/1)
:shutdown
# function compute PTR (internal), INT (input/output) nb
:label compute
:flag CASCADE "compute"
:memory BLN -> &P
:int.div 1000 @(P/1) -> (P/1)
:int.cmp @(P/1) < 100 -> &@&P
:call sub_compute P :when @&@&P TRUE
:return
:label sub_compute
:int.div 100 @(P/1) -> (P/1)
:return
:label recover
:debug BREAK "recover"
1 -> (P/1)
:return
END
MEMORY nb
END
Relancez une nouvelle fois en mode débugueur avec la valeur 0. Lorsque le point d'arrêt est atteint, la fenêtre du processeur doit ressembler à :
Cette fois, le drapeau est dans le registre "Cascaded flags", et il est présent également dans la fonction gestionnaire d'interruption.
Tout comme les gestionnaires d'interruption, lorsqu'un drapeau est cascadé, il est propagé à tous les appels de fonctions faits depuis la fonction où est levé le drapeau.
:flag chaine_drapeau
peut être utilisée pour lever un drapeau dans la fonction courante.:flag CASCADE chaine_drapeau
peut être utilisée pour lever un drapeau dans la fonction courante et toutes les fonctions appellées depuis la fonction courante.Lever un drapeau n'est véritablement utile que si sa présence peut être testée. Modifiez le code :
#!/usr/bin/env svm
DESCRIPTION
Flags example
END
LOG
DEBUG "Flags" STYLE "default"
PLUGIN "svmcom.so"
PLUGIN "svmint.so"
OPTION -i INT nb
PROCESS "application"
CODE "main" INLINE
:interruption CASCADE NUMERIC recover
:memory (PTR, INT)/parameters
@&nb -> (parameters/1)
:call compute parameters
:com.message @&nb ": " @(parameters/1)
:shutdown
# function compute PTR (internal), INT (input/output) nb
:label compute
:flag CASCADE "compute"
:memory BLN -> &P
:int.div 1000 @(P/1) -> (P/1)
:int.cmp @(P/1) < 100 -> &@&P
:call sub_compute P :when @&@&P TRUE
:return
:label sub_compute
:flag CASCADE "sub_compute"
:int.div 100 @(P/1) -> (P/1)
:return
:label recover
:debug BREAK "recover"
:return :when "sub_compute" RAISED
1 -> (P/1)
:return
END
MEMORY nb
END
Lancez l'application en mode débugueur avec les valeurs 0 puis 10000 :
./drapeaux.svm -i 0
0: 100
./drapeaux.svm -i 10000
10000: 0
Dans le cas où l'application lève une exception depuis la fonction "sub_compute", le traitement de l'erreur devient différent grâce au test de présence du drapeau "sub_compute". L'application ne répond plus 1 mais 0 dans ce cas.
La présence d'un drapeau peut être testé avec la condition chaine_drapeau RAISED
Les drapeaux peuvent ainsi servir de booléens situés dans le processeur, évitant la peine de les localiser dans la mémoire pour chaque fonction.
Vous venez de voir comment manipuler les drapeaux du processeur.
Ces drapeaux sont rarement utiles dans le code, mais peuvent être salvateurs dans certaines circonstances précises.
Les extensions qui désirent manipuler la pile de retour du processeur peuvent également faire usage des drapeaux pour leur fonctionnement.