(C'est une question extrêmement novice).
J'ai étudié un peu les machines virtuelles.
Il s'avère que beaucoup d'entre eux sont conçus de manière très similaire aux ordinateurs physiques ou théoriques.
J'ai lu que la machine virtuelle Java, par exemple, est une «machine à pile». Ce que cela signifie (et corrigez-moi si je me trompe), c'est qu'il stocke toute sa "mémoire temporaire" sur une pile et effectue des opérations sur cette pile pour tous ses opcodes.
Par exemple, le code source 2 + 3
sera traduit en bytecode similaire à:
push 2
push 3
add
Ma question est la suivante:
Les machines virtuelles sont probablement écrites en C / C ++, etc. Si tel est le cas, pourquoi la machine virtuelle Java n'exécute-t-elle pas le code C suivant: 2 + 3
..? Je veux dire, pourquoi a-t-il besoin d'une pile ou des "registres" d'autres ordinateurs virtuels - comme dans un ordinateur physique?
Le processeur physique sous-jacent prend en charge tout cela. Pourquoi les auteurs de machines virtuelles n'exécutent-ils pas simplement le code-octet interprété avec des instructions "habituelles" dans la langue avec laquelle la machine virtuelle est programmée?
Pourquoi les machines virtuelles doivent-elles émuler du matériel alors que le matériel actuel le fait déjà pour nous?
Encore une fois, très newbie-ish questions. Merci de votre aide
la source
printf("hi");
: s'agit-il d'une machine virtuelle? Il n'a pas de "pile" ou "registres" et rien.Réponses:
Une machine, virtuelle ou non, a besoin d’un modèle de calcul décrivant comment le calcul est effectué. Par définition, dès qu'il calcule, il implémente un modèle de calcul. La question est alors: quel modèle devrions-nous choisir pour notre machine virtuelle? Les machines physiques sont limitées par ce que l’on peut faire de manière efficace dans le matériel. Mais, comme vous le constatez, les machines virtuelles ne sont pas soumises à de telles contraintes. Elles sont définies dans un logiciel utilisant des langages de haut niveau arbitrairement.
En fait, il existe des machines virtuelles de haut niveau, telles que vous les décrivez. Ils s'appellent les langages de programmation . Le standard C, par exemple, consacre l’essentiel de ses pages à la définition d’un modèle pour la "machine abstraite en C", qui décrit le comportement des programmes C et, par extension, la manière dont un compilateur C conforme (ou un interpréteur) se conforme. Devrait se comporter.
Bien sûr, nous n’appelons généralement pas cela une machine virtuelle. Une machine virtuelle signifie généralement quelque chose de niveau inférieur, plus proche du matériel, non destiné à être programmé directement, conçu pour être exécuté efficacement. Ce biais de sélection signifie que quelque chose qui accepte du code composable de haut niveau (comme ce que vous décrivez) ne serait pas considéré comme une machine virtuelle, car il exécute du code de haut niveau.
Mais pour aller droit au but, voici quelques raisons de créer une machine virtuelle (comme dans quelque chose ciblé par un compilateur de code-octet) basée sur des registres ou similaire. Les machines à empiler et à enregistrer sont extrêmement simples. Il y a une séquence d'instructions, un certain état et une sémantique pour chaque instruction (une fonction State -> State). Pas de réduction d'arbres complexes, pas de priorité des opérateurs. Son analyse, son analyse et son exécution sont très simples, car il s'agit d'un langage minimal (le sucre syntaxique est compilé) et conçu pour être lu par une machine plutôt que par un humain.
En revanche, analyser même les langages de type C les plus simples est assez difficile et son exécution nécessite des analyses non locales telles que la vérification et la propagation de types, la résolution des surcharges, la maintenance d'une table de symboles, la résolution des identificateurs de chaîne , la transformation de texte linéaire en AST , etc. Il s’appuie sur des concepts naturels pour l’homme, mais doit être minutieusement mis au point par des machines.
Le bytecode de la machine virtuelle Java, par exemple, est émis par
javac
. Il n’a pratiquement jamais besoin d’être lu ou écrit par des humains, il est donc naturel de l’orienter vers la consommation par des machines. Si vous optimized pour l' homme, la machine virtuelle Java serait juste à chaque démarrage lire le code, l' analyser, analyser est, puis le convertir en une représentation intermédiaire ressemblant à un tel modèle simplifié de la machine de toute façon . Pourrait aussi bien couper l'homme du milieu.la source
System.out.println("hi");
- dire compiler en une instruction sur une pile,int a = 7
est compilé en une instruction sur la pile, etc.) rend l'exécution du programme simple et plus efficace?2 + 3
est compilé pourpush 2 push 3 add
. L'add
étape à l'extrémité est exécutée par la machine virtuelle Java de toute façon en exécutant le code C2 + 3
. Les programmeurs de la machine virtuelle Java n'ont aucun autre moyen de le faire. Pourquoi ne pas le compiler2 + 3
et laisser la machine virtuelle exécuter simplement le code C2 + 3
(en supposant qu’il soit écrit en C) immédiatement?2 + 3
dans le code source de la machine virtuelle, car celle-ci doit fonctionner avec n'importe quel programme effectuant des opérations dans n'importe quel ordre. Construire du code source en C et passer à une implémentation C ne fait que poser le même problème à la mise en œuvre C (et cela ne peut pas être fait facilement, encore moins efficacement). Une structure de données doit être décrite pour que le programme puisse être interprété et compilé au format JIT. Le "code source lisible par l'homme" est un choix épouvantable de structure de données pour les raisons exposées ci-dessus.a + b
? Ensuite, les valeurs à ajouter ne proviennent pasi.argument{1,2}
, elles sont chargées à partir de variables locales. Qu'en est- ilfrobnicate(x[i]) + (Foo.bar() * 2)
? En utilisant cette conception, il n'y a qu'une seuleadd
opération (pourint
) et cela fonctionne indépendamment de la façon dont les addend ont été calculés. De plus, une instruction qui ajoute uniquement des littéraux entiers serait inutile: son résultat pourrait tout aussi bien être pré-calculé (c'est-à-direadd(2,3)
qu'il devrait l'êtrepush(5)
).Cette réponse se concentre sur la machine virtuelle, mais en réalité elle s’applique à n’importe quelle machine virtuelle.
Ce n’est pas le cas, mais cela rend la machine virtuelle beaucoup plus simple et portable: une machine virtuelle qui émule le matériel peut utiliser le même modèle de calcul que n’importe quel processeur matériel.
La JVM, en particulier, a été conçue pour la portabilité. Elle a même été conçue pour pouvoir être mise en œuvre matériellement (il est peut-être difficile de le croire aujourd’hui, mais l’ origine de Java était dans le monde des systèmes embarqués, en particulier les contrôleurs pour la télévision interactive. ).
Si vous avez un objectif de ce type, il est souhaitable que la machine virtuelle fonctionne aussi près que possible d'une machine physique, car la conversion en code machine réel devient plus facile et donc plus rapide. Une fois que vous avez les codes d'opération de la machine virtuelle, en théorie, tout ce que vous avez à faire est de les convertir en codes d'opération de la CPU sur laquelle le programme est exécuté. En pratique, ce n'est pas si simple.
L'utilisation d'un modèle de machine virtuelle basé sur une pile présente l'avantage de pouvoir être facilement transféré à la fois sur des machines à registre et sur des machines à pile, alors que l'inverse n'est pas nécessairement vrai. Une machine virtuelle basée sur des registres devrait émettre des hypothèses sur le nombre de registres, leur taille, etc. Avec une machine à pile, aucune hypothèse de ce type n'est nécessaire.
Eh bien, c’est ce que font ces machines virtuelles: elles interprètent le bytecode. Même la machine virtuelle le fait effectivement, du moins avant que JIT (juste à temps) n’intervienne: elle interprète les codes d’octet et exécute les instructions dans le langage dans lequel elle a été écrite (généralement C ou C ++, mais il en existe même un écrit). en JavaScript, Doppio ). Notez cependant que même ces déclarations ont été traduites en code machine par un compilateur et ont en fait une apparence très similaire à celle du compilateur Java, à savoir qu’elles utilisent des registres et la pile pour effectuer leur travail. Notez que l'utilisation des langages "interprétés" vs "compilés" devient un peu floue à ce stade.
la source
Pourquoi les machines virtuelles doivent-elles être des «machines empilées» ou des «machines enregistreuses», etc.?
Ils ne. Si vous avez besoin d'une machine virtuelle, cela peut être n'importe quoi.
Les machines virtuelles existantes sont apparues comme des solutions aux situations suivantes: Une idée vraiment brillante m'est venue à la tête, j'ai inventé un nouveau langage de programmation! Mais je dois générer du code. (Quelle tâche ennuyeuse!) Mais je ne veux pas générer de code i8086 parce que c'est moche, et je ne veux pas générer de code 68k car tout le monde utilise Intel. Il y a aussi VAX, mais je n'ai ni VAX, ni ordinateur, ni livre VAX. Par conséquent, je vais générer du code pour un processeur qui n'existe pas physiquement et l'implémenter dans un logiciel. La spécification de cette VM fera un chapitre de ma thèse. En théorie, il sera possible de le compiler en code natif de tout processeur, mais ce ne sera pas moi.
D'autre part, la notation telle que "2 + 3" ne sera probablement pas utilisée par les ordinateurs virtuels dans un avenir prévisible, car elle implique de nombreuses transformations avant que quelque chose puisse être exécuté.
la source
Pour répondre à la question qui a été posée. Le terme "MACHINE virtuelle" signifie que TOUS les logiciels / matériels sont simulés / émulés. Si vous utilisez le logiciel / matériel sous-jacent pour exécuter les instructions, vous n'avez pas de machine virtuelle, vous avez un compilateur / interprète.
la source