"Some" time ago on the Z80? I build a small Z80 computer in the last months and wrote a CPM2.2 BIOS and an interface to an SD card to use it as a floppy using an Arduino. It's a really nice processor but quite old, but it's relatively nice to program in assembler for it. And it is a great processor to learn some assembly.
However, I'm not going to write my VM in assembler, I will stick to C. I designed another VM some time ago using a register based approach but the instructions are getting bigger as you need to store more information. This is my first stack-based approach and it seems to be not that bad at all. And I don't need any register allocation stuff.
The register allocation algorithms are complex as I expected and read in a nice (old) book available as free download as of today:
Understanding and Writing Compilers.
I've got an
RPN calculator from HP which I'm using regularly. My VM is quite similar to such an RPN calculator as there is a limited stack and a limited number of places for variables (e.g. from A to Z).
Many arithmetic opcodes have two addressing modes: (a) do the operation with two values from stack, (b) one operand from stack and the second one is given by an 8bit signed immediate value trailing the opcode. I expect that a range from -128 to 127 is enough for many operations. I had a third addressing mode at first with a 16bit signed immediate value, but excluded it as it took away too much space for other opcodes.
I ran almost out of space, even though stack based machines usually have a good density as the destination (and source) is implicitly defined. And density is the most important aspect for this VM. Reading from SD card is quite expensive as it consumed very much time.
I wish I had more RAM, but it's a nice challenge to squeeze as much information into a small amount of memory as you can. And writing a compiler is quite fun as well. It's a compiler with many small passes where every pass does some small adjustments e.g. optimise to get an executable.
And here is a preview of the syntax of the programming language:
- Code:
PROC MAIN(TEST: X, MX:Y)
LET X = 20 + D + 10 * 3 + 3 * E + 99 - 6;
LET *X = "Hallo!";
LET X = ABS(-1);
ALIAS TEST2 : X + 100;
PRINT(*X);
PRINT(1+1);
TEST = 100 + 100 * (10 + D) + TEST;
PRINT("Is 0 < X < 100?");
IF NOT (0 < X AND X < 100) OR B = 0 THEN
PRINT("YES!", Test2);
ELSE
PRINT("NO!");
ENDIF;
FOR X = 100 + 2 DOWNTO 100+2-33 + TEST2 STEP 1 DO
PRINT(X, "Hallo!", 2);
IF X MOD 2 = 0 THEN
PRINT("EVEN!");
ENDIF;
// Test1
ENDFOR;
WHILE X > 1 DO
X = X - 1;
ENDWHILE;
ENDPROC
FUNC FAK(N:N)
IF 3 > 2 THEN
PRINT("WOW!");
ENDIF;
RETURN N * FAK(N);
ENDFUNC
So, no GOTO but structured programming.
But no stack frames or local variables due to the small RAM...
I attached the instructions I want to implement in the VM to do calculations and communicate with the game itself. It's a ODS (for Libre-/OpenOffice) and an XLS (for Excel) file in a zip as "ods" and "xls" cannot be uploaded directly.
- Attachments
-
- opcodes_ods_and_xls.zip
- opcodes as XLS (Excel) and ODS (Libre/OpenOffice Calc) in a zip
- (26.5 KiB) Downloaded 324 times