Je veux construire une machine virtuelle, y a-t-il de bonnes références? [fermé]

22

Je cherche à construire une machine virtuelle comme un moyen indépendant de la plate-forme pour exécuter du code de jeu (essentiellement des scripts).

Les machines virtuelles que je connais dans les jeux sont plutôt anciennes: Z-Machine d' Infocom , SCUMM de LucasArts , Quake 3 d' id Software . En tant que développeur .net, je connais le CLR et j'ai examiné les instructions CIL pour obtenir un aperçu de ce que vous implémentez réellement au niveau d'une machine virtuelle (par rapport au niveau de la langue). J'ai également essayé un peu le 6502 Assembler au cours de la dernière année.

Le truc, c'est que maintenant que je veux en implémenter un, je dois creuser un peu plus. Je sais qu'il existe des machines virtuelles basées sur la pile et les registres, mais je ne sais pas vraiment laquelle est meilleure dans quoi et s'il existe des approches plus ou hybrides. J'ai besoin de gérer la gestion de la mémoire, de décider quels types de bas niveau font partie de la machine virtuelle et de comprendre pourquoi des choses comme ldstr fonctionnent ainsi.

Mon seul livre de référence (à part les éléments Z-Machine) est le CLI Annotated Standard , mais je me demande s'il y a une meilleure conférence, plus générale / fondamentale pour les VM? Fondamentalement, quelque chose comme le Dragon Book , mais pour les machines virtuelles? Je connais l' art de la programmation informatique de Donald Knuth qui utilise une machine virtuelle basée sur un registre, mais je ne sais pas dans quelle mesure cette série est toujours applicable, d'autant plus qu'elle n'est toujours pas terminée?

Clarification: L'objectif est de construire une VM spécialisée. Par exemple, la Z-Machine d'Infocom contient des codes d'opération pour définir la couleur d'arrière-plan ou jouer un son. J'ai donc besoin de comprendre combien va dans la machine virtuelle en tant que OpCodes par rapport au compilateur qui prend un script (langage TBD) et génère le bytecode à partir de celui-ci, mais pour cela, je dois comprendre ce que je fais vraiment.


¹ Je sais, la technologie moderne me permettrait d'interpréter à la volée un langage de script de haut niveau. Mais où est le plaisir là-dedans? :) C'est aussi un peu difficile à google car les machines virtuelles sont aujourd'hui souvent associées à la virtualisation de système d'exploitation de type VMWare ...

Michael Stum
la source
6
notez que pour qu'une machine basée sur une pile soit complète, elle a besoin de mémoire en dehors de la pile, sinon ce n'est qu'un PDA
ratchet freak
1
La première question est: jusqu'où voulez-vous aller? Je n'ai jamais regardé SCUMM / SCUMMVM mais je suppose que c'est un niveau assez élevé de savoir que les choses graphiques se déplacent, etc. c.-à-d. les instructions de l'assembleur), puis une première version d'une machine virtuelle est une boucle, do { switch(opcode) {case OP1: ... case OP2: ...} while (nextop);puis peut-être un compilateur ... et puis le plaisir commence - optimisation pour que cela fonctionne réellement
johannes
3
Essayez de commencer par implémenter un runtime Forth simple.
SK-logic
1
Comment est exactement Quake 3une machine virtuelle?
Ramhound
3
@Ramhound les moteurs id tech utilisent depuis longtemps une forme de virtualisation interne, cet article ou les informations de Wikipedia pourraient mieux expliquer.
Daniel B

Réponses:

18

Je commencerais par vérifier Lua . À la fois comme exemple d'implémentation et comme machine virtuelle / langage très utilisable dès le départ si vous décidez finalement de ne pas lancer le vôtre.

Le code source est très lisible, et il y a aussi le code source annoté . Et certains documents de conception rédigés par l'auteur principal, Roberto Ierusalimschy.

Enfin, si vous choisissez de l'utiliser au lieu du vôtre, vous constaterez qu'il a longtemps été un favori parmi les développeurs de jeux et qu'il existe une implémentation JIT très performante .

À propos de la pile par rapport au registre, je pense que les machines virtuelles basées sur la pile sont plus faciles à concevoir, mais le compilateur peut être plus complexe. Comme le note le document Iesualimschy, Lua a été l'une des premières machines virtuelles de langage basées sur un registre, mais par la suite, plusieurs autres ont vu le jour, notamment LLVM, Dalvik et certaines machines virtuelles JavaScript modernes.

Javier
la source
2
À propos des machines pile vs registre: Je me souviens d'une citation des développeurs Parrot / Perl6: "construire une machine basée sur un registre est plus difficile, mais nous bénéficions de tonnes de recherches existantes pour notre côté compilateur" (non littéral)
johannes
+1 Lua a une excellente implémentation de bytecode et une conception très propre pour en savoir plus sur les machines virtuelles. En outre, vous constaterez que de nombreuses personnes ont personnalisé Lua pour leurs propres besoins, ce qui montre qu'il est assez extensible si vous ne voulez pas recommencer à zéro.
CodexArcanum
Je traverse toujours ça. Un autre excellent document du développeur sur la VM: inf.puc-rio.br/~roberto/talks/lua-ll3.pdf
Michael Stum
2

Je n'ai pas de ressources spécifiques pour vous mettre en relation pour le moment, mais j'ai fait des recherches sur un sujet similaire dans le passé et j'ai trouvé que la machine virtuelle Smalltalk était également une bonne aide à l'apprentissage. Il existe de nombreux articles universitaires et articles écrits sur les codes d'octets utilisés par Smalltalk, ainsi que des interprètes et des machines virtuelles pour utiliser ce bytecode. Une recherche Google pour smalltalk vm implementationou smalltalk bytecode interpreterdevrait produire beaucoup de matériel de lecture.

Si vous souhaitez voir du code source ou essayer une implémentation, je recommande les versions Squeak ou Pharo.

Le langage / VM Self associé peut également vous intéresser, car Self est essentiellement Smalltalk avec des objets basés sur des prototypes (similaires à JavaScript).

CodexArcanum
la source
0

Je commencerais par analyser comment le code source [script] pénètre dans votre machine ou environnement d'exécution.

Si vous avez quelque chose comme dans les documents HTML, <a onclick="dosomething();">vous aurez besoin d'un compilateur très rapide, la vitesse d'exécution du bytecode n'a pas vraiment d'importance dans ce cas. Si vos cas d'utilisation sont plus proches de Java / .NET où vous pouvez vous permettre une compilation complète, l'architecture VM et la structure de bytecode seront plus proches des bytecodes Java ou IL.

Un autre critère est ce que j'appelle "gluosité". À l'origine, les scripts ont été développés en tant que langages de collage - les scripts définissent simplement la manière de connecter les différentes fonctions natives entre elles (Perl, Python, Ruby, JS). Dans ce cas, l'efficacité de VM et bytecode est beaucoup moins critique que dans le cas de Java / .NET lorsque la plupart de votre code sont des fonctions écrites dans le langage lui-même.

Et le dernier critère majeur que j'utiliserais est l'extensibilité de votre langue. Si vous envisagez d'ajouter à votre langage d'exécution de nombreux objets / fonctions natifs implémentés en C ++, par exemple, votre architecture de machine virtuelle devrait être "pratique" pour l'intégration avec C ++. Par exemple: si vous prévoyez d'exposer au script des objets C ++ tels qu'ils sont, alors la seule option pour vous sera le comptage de références comme une gestion de tas (comme Python, voir boost :: python comme exemple d'intégration). Si vous prévoyez d'utiliser un tas / GC de déplacement / compactage, alors ce sera une autre histoire. La façon dont Lua ajoute des éléments natifs à l'exécution est un peu délicate [pour les développeurs C ++].

En d'autres termes, essayez de définir d'abord votre cas d'utilisation typique et il sera plus facile de suggérer quoi lire pour vous.

c-sourire
la source
1
Les compilateurs JavaScript modernes sont assez complexes, et bien la question est toujours de savoir quelle optimisation du code généré vous mettez.
johannes
Les performances d'exécution de Javascript sont importantes. Pas pour les petits scripts, mais pour les grands sites JS lourds, qui constituent pour le meilleur ou pour le pire une partie importante des sites les plus populaires. Il y a une raison pour laquelle les moteurs JS utilisent des compilateurs JIT (V8 n'a même pas d'interprète, il va directement au code machine).
@delnan: le cas d'utilisation de JS est très différent, disons, de Python. En Python, lorsque vous avez besoin de quelque chose comme l'implémentation d'un algorithme de lancer de rayons, vous allez créer une bibliothèque native et l'appeler à partir d'un script. Cela sera toujours plus rapide (ou du moins pas plus lent) que n'importe quelle solution JIT. Dans le domaine JS, vous n'avez pas autant de luxe que le code natif, donc la seule option pour vous est d'essayer de rendre votre machine virtuelle JS aussi rapide que possible. Mais encore une fois, avec le prix. L'évaluation de "dosomethingnative ()" en HTML "<button onclick =" dosomethingnative () "> dans un interpréteur simple peut être de plusieurs ordres de grandeur plus rapide qu'en V8.
c-smile
@ c-smile Mon point exactement.
@delnan: mais mon point est tout à fait différent: analysez les cas d'utilisation courants et alors seulement vous pourrez décider du type d'architecture de VM, de la syntaxe du langage, etc. dont vous aurez besoin.
c-smile