DEV Community

Alec Sanchez
Alec Sanchez

Posted on • Edited on

My Julia VM and what I learned

Hello there, Alec here! This is my first post, so if you have any tips or feedback, feel free to comment!

GitHub repo:

GitHub logo MoxyFoxy / Julia-Virtualized-CPU

Julia Virtualized CPU, just an odd passion project

Julia-Virtualized-CPU

Julia Virtualized CPU, will possibly be used for a video game I'm making. This was made as a fun little side project to learn Julia, and is not meant to be a faithful recreation of Assembly or how a CPU truly works. While it is faithful to some portions, it's not meant to be a 100% perfect virtualization. There are many limitations that I may decide to change, depending on if I feel the want to come back to this project.

Infrastructure

The CPU has four 16-bit registers, A (accumulator), B (open register), C (count register), and D (data register). There are also three 16-bit pointers, the RP (read pointer), WP (write pointer), and SP (stack pointer). There is currently only a single interrupt, the UOI, or User Input Overflow Interrupt, which defaults to going back to the first line of code for now, may change later. The CPU…

Introduction

You might be asking "Alec, why are you going on and on about a project you made three months ago and haven't updated in a month?"

Shush. For some odd reason, I unconditionally love this project despite its many, many flaws.

What is my VM?

I created a Julia Virtual Machine (VM) to run my own custom instruction set. Why did I do this? It actually allowed me to both learn Julia and Assembly at the same time! Let's delve deeper into why this is, and how it actually greatly benefited my learning.

For Julia, I wanted some project idea as an excuse to learn Julia, as I was (and still am) very interested in the language. I was also interested in learning Assembly, but the current common languages seemed so daunting to use that I became somewhat discouraged. My virtual machine was made with myself in mind so that I could more easily learn Assembly. I knew I couldn't make it as close to something like x86 as I'd like, but a simple start is better than no start at all.

Code Examples and Explanation

Here's a "Hello World!" example in x86 (Windows):

This example shows how to go directly to the Windows API and not link in the C Standard Library.

    global _main
    extern  _GetStdHandle@4
    extern  _WriteFile@20
    extern  _ExitProcess@4

    section .text
_main:
    ; DWORD  bytes;    
    mov     ebp, esp
    sub     esp, 4

    ; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
    push    -11
    call    _GetStdHandle@4
    mov     ebx,

(Code pulled out from the answer)

    global _main
    extern  _GetStdHandle@4
    extern  _WriteFile@20
    extern  _ExitProcess@4

    section .text
_main:
    ; DWORD  bytes;    
    mov     ebp, esp
    sub     esp, 4

    ; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
    push    -11
    call    _GetStdHandle@4
    mov     ebx, eax    

    ; WriteFile( hstdOut, message, length(message), &bytes, 0);
    push    0
    lea     eax, [ebp-4]
    push    eax
    push    (message_end - message)
    push    message
    push    ebx
    call    _WriteFile@20

    ; ExitProcess(0)
    push    0
    call    _ExitProcess@4

    ; never here
    hlt
message:
    db      'Hello, World', 10
message_end:
Enter fullscreen mode Exit fullscreen mode

And here's a "Hello World!" example in my instruction set (in the least lines):

strwrite Hello World!
print 12
Enter fullscreen mode Exit fullscreen mode

It's significantly simpler, isn't it? There are better ways to do it (even in my own instruction set), but this highlights very well the stark difference between the two. I tailor-made this Assembly language based on what would help me learn the most, and though there are some annoying aspects (such as the print instruction and how jumps are absolute lines), but I believe it really helped me achieve a greater understanding of Assembly than I had earlier. Though I didn't learn a specific common instruction set, I still learned the overall concepts behind the code and how different, but sometimes similar, Assembly is to higher-level languages.

My VM is a crappy, unoptimized mess, that I understand. It's not made to be a modern, optimized VM. It was made for me to learn Julia (and all of its quirks, like the fact that you can't set types, even if they're the same, multiple times for a variable name, EVEN IF they are in different local scopes) and Assembly at the same time. I believe it achieved its goal incredibly well and I wholeheartedly recommend other beginners to do something similar. It's a great way to learn the odd quirks of a higher-level language while simultaneously learning the concepts behind Assembly code and how you could apply it in other instruction sets and architectures.

Conclusion

This project, though the VM isn't really all that close to how a real CPU functions and how instruction sets work (especially on OS-level integrations), I believe it helped me grow as a programmer in both a high-level and low-level aspect. While learning Julia, I was able to easily wrap my head around Assembly in a comfortable environment. This really is the best personal project I've made (and the only I've fully completed thus far) and suggest other beginner to not follow what I did unconditionally because I'm some guy with the time to waste posting an article, but suggest they understand why I made this project and what I was thinking going into it, then use that mindset to create their own version that helps THEM learn the best.

Thank you for reading, and have an amazing day!

Top comments (0)