Domanda

Sto cercando di costruire una VM in un gioco e mi chiedevo se qualcuno fosse a conoscenza di VM davvero semplici (pensavo che RISC / PIC fosse vicino a quello che volevo) che di solito vengono utilizzate per progetti embedded come i robot di controllo , motori, sensori, ecc. La mia principale preoccupazione è dover scrivere un compilatore / assemblatore se eseguo il mio. Sarebbe bello usare gli strumenti che sono già là fuori o nella sua forma più semplice solo un compilatore C che può compilare per esso :-p.

Non voglio davvero reinventare la ruota qui, ma ho anche bisogno di migliaia di questi che corrono in un mondo virtuale, quindi devono essere il più semplice e veloce possibile. Come ha già detto una persona, anche a me non interessano i problemi del mondo reale, come i tempi, gli autobus e tutte quelle cose divertenti. Penso che i loro orologi virtuali saranno limitati a qualcosa di piuttosto lento; e alla fine dovrò probabilmente esaminare la compilazione nativa per renderli ancora più veloci, ma per ora sto solo mettendo insieme i prototipi per ottenere una prova generale del concetto.

Come input, sto pianificando sensori di distanza, luce, materiale e touch montati attorno al corpo cilindrico (16, forse 32 di essi), quindi semplicemente 2 motori per l'uscita direzionale per controllare una sorta di ruota su ciascun lato. essenzialmente l'elaborazione non sarà troppo faticosa e il mondo sarà abbastanza semplice in modo che la macchina non debba gettare molta potenza di elaborazione in compiti semplici.

In termini di memoria, mi piacerebbe che fossero in grado di archiviare dati sufficienti per essere lasciati soli per un paio di giorni senza intervento per la creazione di mappe e la raccolta di statistiche. Non mi piace che 8 bit lo taglierebbe per l'elaborazione o la memoria, ma 16 bit sarebbe sicuramente un contendente. 32 e 64 bit lo spingerebbero e non c'è modo di avere più di 1 MB di memoria ciascuno, probabilmente più vicino a 256-512k. (Bill uno ha detto che 640k sarebbero sufficienti, quindi perché non posso !!)

È stato utile?

Soluzione

se vuoi qualcosa di radicato nel mondo reale, uno dei microcontrollori RISC integrati più utilizzati è la famiglia PIC. google offre diversi emulatori, ma non credo che la fonte sia disponibile per la maggior parte.

un'altra possibilità è QEMU, che emula già diverse varietà ARM.

e, naturalmente, se non sei interessato a emulare un dispositivo del mondo reale, prestazioni molto più semplici e migliori sarebbero il rollback del tuo. con solo ciò di cui hai bisogno e non entrare nel caos di flag di stato, bit di overflow, larghezza del bus limitata, temporizzazioni RAM, ecc.

Altri suggerimenti

Ho scritto Wren per un amico che voleva un linguaggio VM in esecuzione su un controller incorporato con circa 16K di RAM. (Ma consente fino a 64k per processo nel codice come scritto.) Include un compilatore per un linguaggio di programmazione stupido. È tutto abbastanza semplice e non ha visto molto uso, ma è proprio quello che hai descritto nel tuo primo paragrafo.

La FORTH "macchina virtuale" è semplice come arrivano. Spazio di indirizzi a 16 bit (in genere), parole di dati a 16 bit, due pile, memoria. Loeliger's " Threaded Interpretive Languages ??" ti dice molto su come costruire un interprete FORTH su uno Z80.

Se vuoi semplice, considera il Manchester Mark I. Vedi pagina 15 di questo PDF . La macchina ha 7 istruzioni. Ci vuole circa un'ora per scrivere un interprete. Sfortunatamente, le istruzioni sono piuttosto limitate (ecco perché praticamente una specifica completa della macchina può stare su una pagina).

L'approccio di Javier al lancio del proprio è molto pragmatico. Progettare e creare una macchina minuscola è un compito di due giorni, se quello. Ho creato una piccola VM per un progetto qualche anno fa e mi ci sono voluti due giorni per scrivere la VM con un semplice debugger visivo.

Inoltre - deve essere RISC? Puoi scegliere, per esempio, 68K per i quali esistono emulatori open source e 68K era un obiettivo ben compreso per gcc.

Many people writing game programs and other applications embed a language into the application to allow users to write small programs.

As far as I can tell, the most popular embedded languages in very roughtly most-popular-first order (although "more popular" doesn't necessarily mean "better") seem to be:

  • domain-specific language custom-designed for this one specific application and used nowhere else
  • Lua a
  • Tcl
  • Python a b, often a simplified subset such as PyMite c
  • Forth
  • JavaScript a
  • Lisp
  • AngelScript a
  • XPL0 a b
  • Squirrel a
  • Haskell a b
  • NPCI (Nano Pseudo C Interpreted) a
  • RoboTalk
  • interpreting some hardware machine language (Why is this the least-popular choice? For good reasons, described below).

You may want to check out the Gamedev StackExchange, in particular questions like "How do you add a scripting language to a game?".

You may want to check out some of the questions here on StackOverflow tagged "embedded language"; such as "Selecting An Embedded Language", "What is a good embeddable language I can use for scripting inside my software?" "Alternatives to Lua as an embedded language?" "Which game scripting language is better to use: Lua or Python?", etc.

Many implementations of these languages use some sort of bytecode internally. Often two different implementations of the same high-level programming language such as JavaScript use two completely different bytecode languages internally ( a ). Often several high-level programming languages compile to the same underlying bytecode language -- for example, the Jython implementation of Python, the Rhino implementation of JavaScript, the Jacl implementation of Tcl, JScheme and several other implementations of Scheme, and several implementations Pascal; all compile to the same JVM bytecode.

details

Why use a scripting language rather than interpreting some hardware machine language?

Why "Alternate Hard And Soft Layers"? To gain simplicity, and faster development.

faster development

People generally get stuff working faster with scripting languages rather than compiled languages.

Getting the initial prototype working is generally much quicker -- the interpreter handles a bunch of stuff behind-the-scenes that machine language forces you to explicitly write out: setting the initial values of variables to zero, subroutine-prolog and subroutine-epilog code, malloc and realloc and free and related memory-management stuff, increasing the size of containers when they get full, etc.

Once you have an initial prototype, adding new features is faster: Scripting languages have rapid edit-execute-debug cycles, since they avoid the "compile" stage of edit-compile-execute-debug cycles of compiled languages.

simplicity

We want the embedded language language to be "simple" in two ways:

  • If a user wants to write a little code that does some conceptually trivial task, we don't want to scare this person off with a complex language that takes 20 pounds of books and months of study in order to write a "Hello, $USER" without buffer overflows.

  • Since we're implementing the language, we want something easy to implement. Perhaps a few simple underlying instructions we can knock out a simple interpreter for in a weekend, and perhaps some sort of pre-existing compiler we can reuse with minimal tweaking.

When people build CPUs, hardware restrictions always end up limiting the instruction set. Many conceptually "simple" operations -- things people use all the time -- end up requiring lots of machine-language instructions to implement.

Embedded languages don't have these hardware restrictions, allowing us to implement more complicated "instructions" that do things that (to a human) seem conceptually simple. This often makes the system simpler in both ways mentioned above:

  • People writing directly in the language (or people writing compilers for the language) end up writing much less code, spending less time single-stepping through the code debugging it, etc.

  • For each such higher-level operation, we shift complexity from the compiler to an instruction's implementation inside the interpreter. Rather than (you writing code in) the compiler breaking some higher-level operation into a short loop in the intermediate language (and repeatedly stepping through that loop in your interpreter at runtime), the compiler emits one instructions in the intermediate language (and you write the same series of operations in your interpreter's implementation of that intermediate "instruction"). With all the CPU intensive stuff implemented in your compiled language ("inside" complex instructions), extremely simple interpreters are often more than fast enough. (I.e., you avoid spending a lot of time building a JIT or trying to speed things up in other ways).

For these reasons and others, many game programmers use a "scripting" language as their "embedded language".

(I see now that Javier already recommended "use an embedded scripting language", so this has turned into a long rant on why that's a good alternative to interpreting a hardware machine language, and pointing out alternatives when one particular scripting language doesn't seem suitable).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top