43 votes

Tutoriel/ressource pour la mise en œuvre de la VM

Je veux mettre en œuvre une machine virtuelle simple pour un langage dynamique, de préférence en C. Quelque chose comme la Lua VM, ou Parrot, ou Python VM, mais plus simple. Existe-t-il de bonnes ressources/tutoriels pour y parvenir, à part regarder le code et les documentations de conception des VM existantes ?

Edit : pourquoi fermer le vote ? Je ne comprends pas - ce n'est pas de la programmation. Veuillez commenter s'il y a un problème spécifique avec ma question.

3 votes

Si vous êtes toujours intéressé, j'ai écrit une VM vraiment très simple en C. Jetez-y un coup d'oeil : github.com/tekknolagi/carp

31voto

Edmund Points 6479

Je suppose que vous voulez une machine virtuelle plutôt qu'un simple interprète. Je pense que ce sont deux points sur un continuum. Un interpréteur travaille sur quelque chose de proche de la représentation originale du programme. Une machine virtuelle travaille sur des instructions plus primitives (et autonomes). Cela signifie que vous avez besoin d'une étape de compilation pour traduire l'un en l'autre. Je ne sais pas si vous voulez travailler sur ce point en premier ou si vous avez déjà une syntaxe d'entrée en tête.

Pour un langage dynamique, vous voulez un endroit qui stocke les données (sous forme de paires clé/valeur) et certaines opérations qui agissent sur elles. La VM maintient le magasin. Le programme qui s'exécute sur elle est une séquence d'instructions (y compris le flux de contrôle). Vous devez définir le jeu d'instructions. Je suggérerais un ensemble simple pour commencer, par exemple :

  • les opérations arithmétiques de base, notamment les comparaisons arithmétiques, l'accès au magasin
  • flux de contrôle de base
  • impression intégrée

Il se peut que vous souhaitiez utiliser une approche de calcul par pile pour l'arithmétique, comme le font de nombreuses VM. Il n'y a pas encore beaucoup de dynamique dans ce qui précède. Pour y parvenir, nous avons besoin de deux choses : la possibilité de calculer les noms des variables à l'exécution (ce qui signifie simplement des opérations sur les chaînes de caractères), et un certain traitement du code comme des données. Cela pourrait être aussi simple que d'autoriser les références aux fonctions.

L'entrée dans la VM devrait idéalement se faire en bytecode. Si vous n'avez pas encore de compilateur, il pourrait être généré à partir d'un assembleur de base (qui pourrait faire partie de la VM).

La VM elle-même est constituée de la boucle :

1. Look at the bytecode instruction pointed to by the instruction pointer.
2. Execute the instruction:
   * If it's an arithmetic instruction, update the store accordingly.
   * If it's control flow, perform the test (if there is one) and set the instruction pointer.
   * If it's print, print a value from the store.
3. Advance the instruction pointer to the next instruction.
4. Repeat from 1.

La gestion des noms de variables calculées peut être délicate : une instruction doit spécifier dans quelles variables se trouvent les noms calculés. Cela pourrait être fait en permettant aux instructions de se référer à un ensemble de constantes de chaînes de caractères fournies en entrée.

Un exemple de programme (en assembleur et en bytecode) :

offset  bytecode (hex)   source
 0      01 05 0E         //      LOAD 5, .x
 3      01 03 10         // .l1: LOAD 3, .y
 6      02 0E 10 0E      //      ADD .x, .y, .x
10      03 0E            //      PRINT .x
12      04 03            //      GOTO .l1
14      78 00            //      .x: "x"
16      79 00            //      .y: "y"

Les codes d'instruction impliqués sont :

"LOAD x, k" (01 x k) Load single byte x as an integer into variable named by string constant at offset k.
"ADD k1, k2, k3" (02 v1 v2 v3) Add two variables named by string constants k1 and k2 and put the sum in variable named by string constant k3.
"PRINT k" (03 k) Print variable named by string constant k.
"GOTO a" (04 a) Go to offset given by byte a.

Vous avez besoin de variantes pour quand les variables sont nommées par d'autres variables, etc. (et les niveaux d'indirection deviennent délicats à raisonner). L'assembleur regarde les arguments comme "ADD .x, .y, .x" et génère le bytecode correct pour l'addition à partir de constantes de chaîne (et non de variables calculées).

0 votes

Bien. Une idée de la ressource à utiliser à partir de là ?

1 votes

@zaharpopv : Je ne suis pas trop sûr de l'implémentation de la fonctionnalité dynamique de votre langage, mais une conception simple de VM comme celle ci-dessus est assez facile pour qu'une fois que vous l'aurez faite, vous sachiez à quel point elle est adaptée et vous pourrez vous permettre de la modifier pour supporter des fonctionnalités plus intéressantes. En outre, l'examen de l'ensemble des instructions de l'interpréteur Python pourrait vous donner quelques idées sur la façon de prendre en charge le dynamisme.

9voto

Brian Campbell Points 101107

Il ne s'agit pas de l'implémentation d'une VM en C, mais comme c'est le dernier onglet que j'ai ouvert avant de voir cette question, j'ai l'impression qu'il faut que je fasse remarquer une chose. article sur l'implémentation d'un compilateur de bytecode QBASIC et d'une machine virtuelle en JavaScript en utilisant l'option <canvas> pour l'affichage. Il comprend tout le code source permettant d'implémenter suffisamment de QBASIC pour faire tourner le jeu "nibbles", et est le premier d'une série d'articles sur le compilateur et l'interpréteur bytecode ; celui-ci décrit la VM, et il promet de futurs articles décrivant également le compilateur.

Au fait, je n'ai pas voté pour clore votre question, mais le vote serré que vous avez obtenu était un double d'un question de l'année dernière sur la façon d'apprendre à mettre en œuvre une machine virtuelle. Je pense que cette question (à propos d'un tutoriel ou de quelque chose de relativement simple) est suffisamment différente de celle-là pour qu'elle reste ouverte, mais vous pourriez vouloir vous référer à celle-ci pour obtenir des conseils supplémentaires.

4voto

RBerteig Points 23331

Une autre ressource à examiner est l'implémentation de la fonction Langage Lua . I code source est en ANSI C89, et est généralement très lisible.

Comme pour la plupart des langages de script à haute performance, l'utilisateur final voit un langage dynamique lisible et de haut niveau (avec des caractéristiques telles que les fermetures, les appels de queue, les chaînes immuables, les nombres et les tables de hachage comme types de données primaires, les fonctions comme valeurs de première classe, et plus encore). Le texte source est compilé en bytecode de la VM pour être exécuté par une implémentation de la VM dont les grandes lignes sont à peu près celles décrites dans le document suivant Réponse d'Edmund .

De nombreux efforts ont été déployés pour que l'implémentation de la VM elle-même soit à la fois portable et efficace. Si vous avez besoin d'encore plus de performances, une compilateur juste à temps du code d'octet VM aux instructions natives existe pour x86 32 bits, et est en version bêta pour 64 bits.

2voto

dead Points 711

Pour commencer (même si ce n'est pas C pero C++ ), vous pourriez jeter un coup d'œil à muParser .

Il s'agit d'un analyseur d'expression mathématique qui utilise un fichier de type simple machine virtuelle pour exécuter des opérations. Je pense que même vous avez besoin de temps pour tout comprendre ; de toute façon ce code est plus simple qu'une VM complète capable d'exécuter une réel programme complet. (A propos, je suis en train de concevoir une libellé similaire en C# - il en est à ses débuts mais les prochaines versions permettront la compilation vers .NET/VM IL ou peut-être une nouvelle VM simple comme muParser ).

Une autre chose intéressante est NekoVM (il exécute les fichiers .n bytecode). C'est un projet open source écrit en C et son langage principal (.neko) est supposé être généré par compilateur source à source technologie. Dans l'esprit du dernier sujet, voir Haxe du même auteur (open source également).

1voto

Jerry Coffin Points 237758

Une possibilité serait de lire Conception et mise en œuvre de machines virtuelles C/C++ . Je dois préciser que si j'ai jeté un coup d'œil à ce livre en librairie, je ne l'ai pas vraiment lu. Il a survécu à mon test habituel consistant à l'ouvrir à quelques pages au hasard pour voir s'il contenait des erreurs évidentes, mais c'est une question de temps. extrêmement un test non scientifique, au mieux. En même temps, il est suffisamment bon pour que (juste pour un exemple) chaque livre d'Herbert Schildt que j'ai regardé ait échoué en moins de cinq minutes...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X