NEW - PDF: l1vm-course-pdf
1: Hello world, if, if+, else
9: logical operators, bit shifting
10: cli arguments
12: assembly VOL I
13: assembly VOL II
14: assembly VOL III
15: assembly VOL IV
16: assembly VOL V
L1VM code details: l1vm-jit-compiler-pdf
The L1VM is a fast, secure and reliable VM. It was built with security in mind. It can run bytecode generated by my Brackets compiler and assembler. Brackets is my own language, which is easy to learn. You can even write programs which are using my SDL/GUI module for graphics output. And you can run multiple threads very easy.
My language Brackets is strongly typed and variable type safe. The L1VM can detect variable overflows (array) and string overflows at runtime. It also can find errors on the stack. If for example an int64 variable is on the stack top and a double number would be taken, then this results in an error!
You can also switch number overflow detection on. So on double numbers there will be errors if a number is “nan” (not a number) or “inf” (infinity).
The range of a variable can be set with the
(x x_min x_max range)
The minimum value and the maximum value are set by
If an assign of
x would be out of range then it is a runtime error! This makes programs which use the new
range keyword more safe.
NEW: Now you can define objects in Brackets for OOP style programming. You can write functions inside the object which are using the object data.
An example is here: math-circle-oop.l1com.
The L1VM runs on Linux (x86_64, Arm), BSD OS: OpenBSD, FreeBSD, DragonFly BSD, Windows 10, 11 via WSL, macOS and Haiku OS. However on Haiku OS the multithreading can’t be used. Maybe this works with later betas.
The VM has an preprocessor, assembler and compiler for my own language Brackets. On the Raspberry Pi the GPIO pins can be used with my GPIO module. Also the serial port can be used.
Linux x86_64 binaries
I made static build binaries for Linux x86_64. They should run on any 64 bit Linux system.
The current L1VM 2.8.0 builds are here: L1VM Linux binaries and libraries.
I did include all modules and their depedencies, so the binaries should run on any Linux system. Here is the sha256 sum of the archive:
NEW: Windows x86_64 binaries
I finally made a port to Windows MSYS2. You need to install MSYS2 to use this! So now the L1VM can run natively on Windows without the need to install the WSL.
I did have to disable the memory bounds checking on the string module. Otherwise it will not work. This strange behaviour is only in the MSYS2 build!
L1VM Windows MSYS2 binaries and libraries.
Here is the sha256 sum of the archive:
L1VM is an incredible tiny virtual machine with RISC (or comparable style) CPU, about 61 opcodes and about 49 KB binary size on X86_64 Linux! The VM has a 64 bit core (256 registers for integer and double float) and can run object code written in Brackets (a high level programming language) or l1asm assembly language.
Code and data are in separated memories for a secure execution. Like in Harvard type CPUs (found now in DSPs or microcontrollers). The opcode set with 61 opcodes is my own opinion how things should work. It does not “copy” other instruction sets known in other “real” CPUs.
I did develop an own programming language “Brackets”, which supports all the features of my VM. Brackets is variable type safe and supports constant variables. Brackets also supports multithreading.
I did develop a fractal rendering program in Brackets assembly.
The design goals are:
- be small - be fast - be simple - be modular
The source code is on my GitHub repository: github.com/koder77/l1vm
You can write programs in my language Brackets. Here is a simple “Hello world!” program:
// hello.l1com // Brackets - Hello world! // #include <intr.l1h> (main func) (set int64 1 zero 0) (set int64 1 x 23) (set int64 1 y 42) (set int64 1 a 0) (set string 13 hello "Hello world!") // print string print_s (hello) print_n ((x y *) a =) print_i (a) print_n exit (zero) (funcend)
$ l1vm prog/hello-2 -q Hello world! 966
So for printing a string some interrupts are used there. In the GitHub repo threre are lots of more advanced examples!
You can do GUI/graphics programs too. Here is a fractal drawing multithreading program example: fractalix-3.2
The L1VM can do multithreading! It is possible by using pthreads.
Here is a GUI example: pov-edit
The gadgets are drawn by my SDL graphics/GUI module.
The L1VM can be expanded by modules (shared libraries). A module has an own API to access the functions from the VM. Here is the list of modules:
Cells - linked neural networks with FANN library ciphersaber - encrypt/decrypt functions crypto - libsodium encrypt/decrypt functions endianess - convert to big endian, or little endian functions fann - FANN neural networks file - file module - read/write files filetools - file functions like copy, create directory, etc. genann - neural networks module gpio - Raspberry Pi GPIO module math - some math functions math-nofp - math module for use without FPU math-vect - math on arrays functions mem - memory allocating for arrays and vectors mem-obj - memory functions to store different variables into one memory array mem-vect - C++ vector memory library mpfr-c++ - MPFR floating point big num library net - TCP/IP sockets module pigpio - Raspberry Pi GPIO module process - start a new shell process rs232-libserialport - RS232 serial port using libserialport rs232 - RS232 serial port module sdl 2.0 - graphics primitves module, like pixels, lines..., and GUI with buttons, lists, etc. string - some string functions time - get time and date
You can use this modules in your own Bracket programs.
And you even can develop your own modules!
I have two examples: a math demo and a switch (like in C). Here is the output of my math library demo:
$ l1vm lib/math-lib -q 3368910609462220170 3.1415926536 3.142 1
The first number is a random number. Which changes on each run. The second and the third numbers are Pi rounded numbers. The last number “1” is the result of the not opcode.
Here is the math library demo:
// math-lib.l1com // math library demo // #include <math-const.l1h> #include <intr.l1h> (main func) (set int64 1 zero 0) (set int64 1 randstart 2003) (set int64 1 random 0) (set int64 1 digits 3) (set int64 1 numstr_len 30) (set int64 1 not_num 0) (set int64 1 not_ret) (set string 30 numstr "") (zero :math_init call) (loadreg) (randstart :math_randinit call) (loadreg) (:math_randint call) (random stpopi) (loadreg) print_i (random) print_n print_d (m_pi@math) print_n // round pi to "digits" (3) digits and store number in string (m_pi@math digits numstraddr numstr_len :double_rounded_string call) (loadreg) print_s (numstr) print_n (not_num :math_not call) (not_ret stpopi) (loadreg) print_i (not_ret) print_n // close module free_mod (zero) exit (zero) (funcend) #include <math-lib.l1h>
Here is the output of my “switch” test program:
$ l1vm prog/switch -q Hello world! 966 y = 42
A “switch” compares two variables and then runs the code in it, if they are equal. This is like in C. Here is a full example:
// switch.l1com // Brackets - Hello world! switch // #include <intr.l1h> (main func) (set int64 1 zero 0) (set int64 1 x 23) (set int64 1 y 42) (set string s 23_str "y = 23") (set string s 42_str "y = 42") (set const-int64 1 23_const 23) (set const-int64 1 42_const 42) (set string s hello_str "Hello world!") (set int64 1 a 0) // print string print_s (hello_str) print_n ((x y *) a =) print_i (a) print_n (switch) (y 23_const ?) print_s (23_str) print_n (break) (y 42_const ?) print_s (42_str) print_n (break) (switchend) exit (zero) (funcend)
There are more demos in my GitHub repository! For the modules there are more demo programs.