Simple Virtual Machine in C
github.com
github.com
I hope one day my VM/Assembler will become as fully featured as this.
My last major achievement was implementing multiplication in my assembly language [2] so I've got a lot of catching up to do with this author!
[0] - https://github.com/gravypod/computer/blob/master/isa/main.c#...
[1] - https://github.com/gravypod/computer/blob/master/isa/instruc...
[2] - https://github.com/gravypod/computer/blob/master/examples/mu...
This must be some sort of generation gap. Because array of pointers for opcodes is like... emulator 101. It's just a jump table.
Glad you're learning and trying stuff though!
(Actually, it doesn't even need to be a switch statement... Just a succession of `if`s works fine.)
I've also found this comment in Python 3.6 source code in ceval.c which is where opcode dispatch is: https://pastebin.com/kuV7UfG0
I wouldn't say it is always a waste of time just because jump tables can be easier to read and manage when you have a decent number of opcodes. Being able to have all your opcodes in separate functions and then just have one single list that shows exactly what opcode maps to what instruction is really nice:
https://github.com/mkilgore/yaji/blob/master/src/op.c#L336
To each his own though, you're right it likely doesn't matter that much performance wise.
FYI, even microcontrollers nowadays have efficient hard multipliers. It would make more sense to emulate floating point multiplication imo.
Anyways, keep up the good work!
Subroutine threading is when the VM code compiles to subroutine call instructions that the host computer can execute directly.
Thanks for the pointer.
[0] - https://eli.thegreenplace.net/2012/07/12/computed-goto-for-e...
- Virtual Machine
- Emulator
- Interpreter
- Finite State Machine
I think your implementation would fit under the traditional definition of a state machine or maybe an interpreter. But most people would not define it as a virtual machine. It is certainly not an operating system running on another operating system which is the most popular definition today. Nor is it as capable as the VM's that run environments such as Java or .NET, which is the other definition people might use.
Right: virtual machine = software implementation of what could be a real machine.
The simplest interpreters execute directly from the AST, but if there's a pass that reduces this to an abstract machine with an ISA, I think it's fair to classify that as a VM.
There are two kinds of VMs: system VMs and process VMs (https://en.wikipedia.org/wiki/Virtual_machine)
Maybe refrain from 'correcting' someone on common definitions if you aren't familiar with the kinds and amount of commonality of all definitions?
"Virtual Machine" does today commonly mean an interpreter based on opcode instructions, aka process VM.
Furthermore, using 'interpreter' for an opcode based VM is less common, I feel like your suggestion goes backwards by your own metric.
> Nor is it as capable as the VM's that run environments such as Java or .NET, which is the other definition people might use.
So I'm curious what you were expecting when you clicked on "Simple Virtual Machine in C" linked to github? Is it likely that someone's open source project is going to compete with the 2 largest and most widely distributed runtimes on the planet?
How do you measure capability? If the VM is Turing complete, is it really less "capable"?
What is the point of your negative comment? Do you want the author to change the title? Do you want other people to never make another VM because Java already has one? And what kind of responses do you hope for next time you share your open source project on HN?
The vast majority of the opcode emulation code is automatically generated from a high(ish) level spec found at https://github.com/ggambetta/libz80/blob/master/codegen/mkta... This saves a ton of error-prone, manual work :)
https://github.com/larsbrinkhoff/nybbleForth/blob/c/nybble.c
The original interpreter was written in Forth, but I'll spare you that and point to the C version.
I was hoping for something more like this "minimum viable hypervisor" or one of the similar projects discussed here:
Simplevisor: Intel x64 Windows-specific hypervisor | https://news.ycombinator.com/item?id=11628554 (2016May:24comments)
Here is my solution in c# ... 33 lines of code.
I was proud of how fast I got it to run instructions, given that I knew nothing about other virtual machines.
https://gist.github.com/mar77i/46bd25504dd9e81d0ca7778efcee4...
I wonder if it's possible to write a interpreter with restrictions on loops etc that can limit/verify programs on the basis of the memory they'd require?
Doesn't mean you couldn't make an useful sub-turing language for resource limited use.
On a final note, nodemcu doesn't really execute "lua instructions", it executes normal machine code like everything else but it ships with lua interpreter/vm firmware.
Does anyone have a link to a simple one that supports concurrency, by chance?
edit: So basically, if one had the p-code machine[0], how might it handle concurrency/threading?
Given a single-CPU VM, you can write an assembly program that implements context switching and the thread control block data structure. Then you write a scheduler (OK, the VM needs a timer/interrupt to trigger the scheduler). thread.start(function) allocates some stack memory and a thread control block, which contains a pointer to `function` and to the stack memory you just allocated. Then `thread.start` inserts our TCB into the scheduler queue. All this stuff is implemented as software in the VM's machine language, it is not part of the VM itself. pthread_create and the Linux scheduler are not implemented in hardware either.
I guess if you want memory protection, you would need the VM to simulate a MMU.
On the other hand, if you actually want programs on the VM to be able to run on multiple CPUs of the host machine, then I agree you need some special support in the VM to do that.
The language is based on Scheme and Common Lisp.
The instruction set is derived from one described in the book Paradigms of Artificial Intelligence Programming by Peter Norvig.
The concurrency primitives are inspired by Erlang.
It's implemented in (old-fashioned) JavaScript but the compiler is self-hosting.