Eu quero construir uma máquina virtual, existem boas referências? [fechadas]

22

Estou procurando construir uma Máquina Virtual como uma maneira independente de plataforma para executar algum código do jogo (essencialmente scripts).

As máquinas virtuais de que conheço os jogos são bastante antigas: a Z-Machine da Infocom , a SCUMM da LucasArts , o Quake 3 da id Software . Como desenvolvedor .net, conheço o CLR e examinei as instruções do CIL para obter uma visão geral do que você realmente implementa no nível da VM (versus o nível do idioma). Eu também me envolvi um pouco no 6502 Assembler durante o ano passado.

O problema é que agora que eu quero implementar um, preciso cavar um pouco mais fundo. Eu sei que existem VMs baseadas em pilha e registradas, mas realmente não sei qual é a melhor em que e se há mais abordagens híbridas. Preciso lidar com o gerenciamento de memória, decidir quais tipos de baixo nível fazem parte da VM e entender por que coisas como o ldstr funcionam da maneira que funcionam.

Meu único livro de referência (além do material Z-Machine) é o CLI Annotated Standard , mas me pergunto se existe uma palestra melhor, mais geral / fundamental para VMs? Basicamente, algo como o Dragon Book , mas para VMs? Estou ciente da Art of Computer Programming de Donald Knuth, que usa uma VM baseada em registro, mas não tenho certeza de quão aplicável essa série ainda é, especialmente porque ainda está inacabada?

Esclarecimento: O objetivo é construir uma VM especializada. Por exemplo, o Z-Machine da Infocom contém OpCodes para definir a cor de fundo ou reproduzir um som. Então, eu preciso descobrir o quanto a OpCodes usa na VM versus o compilador que pega um script (linguagem TBD) e gera o bytecode a partir dele, mas para isso eu preciso entender o que estou realmente fazendo.


¹ Eu sei que a tecnologia moderna me permitiria interpretar rapidamente uma linguagem de script de alto nível. Mas onde está a diversão nisso? :) Também é um pouco difícil de pesquisar no Google porque hoje em dia as Máquinas Virtuais estão frequentemente associadas à Virtualização de SO do tipo VMWare ...

Michael Stum
fonte
6
Note-se que para uma máquina de pilha com base para ser Turing completo que precisa de memória fora da pilha caso contrário é apenas um PDA
aberração catraca
1
A primeira pergunta é: até onde você quer ir? Eu nunca olhei para SCUMM / SCUMMVM, mas suponho que seja um nível bastante alto, sabendo que as coisas gráficas estão se movimentando etc. instruções assembler ou seja) e, em seguida, uma primeira versão de um VM é um loop do { switch(opcode) {case OP1: ... case OP2: ...} while (nextop);, então talvez um compilador ... e, em seguida, começa a diversão - otimização para torná-lo realmente trabalho
Johannes
3
Tente começar com a implementação de um simples tempo de execução Forth.
SK-logic
1
Como exatamente é Quake 3uma máquina virtual?
precisa saber é o seguinte
3
@ Rammound os mecanismos de tecnologia de identificação há muito tempo usam alguma forma de virtualização interna, este artigo ou as informações da Wikipedia podem explicar melhor.
Daniel B

Respostas:

18

Eu começaria verificando Lua . Tanto como uma implementação de amostra quanto como uma VM / linguagem muito útil, se você finalmente decidir não lançar o seu próprio.

O código fonte é muito legível e também existe o código fonte anotado . E alguns documentos de design escritos pelo autor principal, Roberto Ierusalimschy.

Finalmente, se você optar por usá-lo em vez de seu próprio país, você vai descobrir que tem sido por muito tempo um favorito entre os desenvolvedores de jogos, e há um muito alto desempenho implementação JIT .

Sobre pilha versus registro, acho que VMs baseadas em pilha são mais fáceis de projetar, mas o compilador pode ser mais complexo. Como observa o artigo de Iesualimschy, Lua foi uma das primeiras VMs de linguagem baseada em registros, mas depois várias outras surgiram, principalmente LLVM, Dalvik e algumas VMs JavaScript modernas.

Javier
fonte
2
Sobre pilha vs máquinas de: Lembro-me de uma citação de Parrot / Perl6 devs: "a construção de uma máquina baseada registo é mais difícil, mas nós nos beneficiamos de toneladas de investigação existente para o nosso lado compilador" (não literal)
Johannes
O +1 possui uma excelente implementação de bytecode e um design muito limpo para aprender sobre VMs. Além disso, você verá que muitas pessoas personalizaram o Lua para suas próprias necessidades, mostrando que é bastante extensível se você não deseja começar do zero.
CodexArcanum
Ainda estou passando por isso. Outro ótimo documento do desenvolvedor sobre a VM: inf.puc-rio.br/~roberto/talks/lua-ll3.pdf
Michael Stum
2

No momento, não tenho recursos específicos para vinculá-lo, mas pesquisei um tópico semelhante no passado e achei a VM do Smalltalk uma boa ajuda para o aprendizado. Existem muitos artigos e artigos acadêmicos escritos sobre os códigos de bytes usados ​​pelo Smalltalk, além de intérpretes e VMs para escrever para usar esse bytecode. Uma pesquisa no Google por smalltalk vm implementationou smalltalk bytecode interpreterdeve render muito material de leitura.

Se você quiser ver algum código-fonte ou experimentar uma implementação, recomendo as versões Squeak ou Pharo.

O idioma relacionado / VM Self também pode lhe interessar, pois Self é basicamente Smalltalk com objetos baseados em protótipo (semelhante ao JavaScript).

CodexArcanum
fonte
0

Eu começaria analisando como o código-fonte [script] entra na sua máquina ou no ambiente de tempo de execução.

Se você tem algo parecido em documentos HTML <a onclick="dosomething();">, precisará de um compilador muito rápido, pois a velocidade de execução do bytecode não importa muito nesse caso. Se seus casos de uso estiverem mais próximos do Java / .NET, onde você pode permitir a compilação completa, a arquitetura da VM e a estrutura de bytecode estarão mais próximos dos bytecodes Java ou IL.

Outro critério é o que chamo de "glueness". Originalmente, os scripts foram desenvolvidos como linguagens de cola - os scripts apenas definem a maneira de conectar várias funções nativas (Perl, Python, Ruby, JS). Nesse caso, a eficácia da VM e do bytecode é muito menos crítica do que no caso do Java / .NET, quando a maior parte do seu código são funções escritas na própria linguagem.

E o último critério importante que eu usaria é a extensibilidade do seu idioma. Se você planeja adicionar ao tempo de execução da linguagem muitos objetos / funções nativos implementados, digamos, em C ++, sua arquitetura de VM deve ser "conveniente" para integração com o C ++. Por exemplo: se você planeja expor aos objetos C ++ de script como eles são, a única opção para você será a contagem de referência como um gerenciamento de heap (como Python, consulte boost :: python como um exemplo de integração). Se você planeja usar heap / GC móvel / compactador, será uma história diferente. A maneira de Lua de adicionar coisas nativas ao tempo de execução é um pouco complicada [para desenvolvedores de C ++].

Em outras palavras, tente definir primeiro seu caso de uso típico e será mais fácil sugerir o que ler para você.

sorriso
fonte
1
Compiladores Modern JavaScript são bastante complexos, e bem a questão não é alwazs quanto a otimização do código gerado você colocou.
Johannes
O desempenho da execução do Javascript é importante. Não para scripts pequenos, mas para sites maiores, pesados ​​para JS, que para melhor ou pior compõem uma parte significativa dos sites mais populares. Há uma razão pela qual os mecanismos JS usam compiladores JIT (o V8 nem sequer tem um intérprete, ele vai direto para o código da máquina).
@ delnan: O caso de uso do JS é bem diferente do Python, por exemplo. No Python, quando você precisa de algo como a implementação do algoritmo de rastreamento de raios, você cria uma biblioteca nativa e a chama de script. Isso sempre é mais rápido (ou pelo menos não mais lento) do que qualquer solução JIT. No domínio JS, você não tem esse luxo como código nativo; portanto, a única opção é tentar tornar sua JS VM o mais rápido possível. Mas, novamente, com o preço. Avaliação do "dosomethingnative ()" em HTML "<button onclick =" dosomethingnative () "> em simples intérprete pode estar em ordens de magnitude mais rápido do que no V8.
c-sorrir
@ c-smile Meu ponto exatamente.
@ delnan: mas o meu argumento é bem diferente: analise casos de uso comuns e só então você poderá decidir que tipo de arquitetura de VM, sintaxe de idioma, etc., será necessário.
C-smile