Following requirements must be met in order to compile and run Viua VM.

CPU architecture

64 bit x86 is supported. 64 bit ARM should also work. Compiling and running Viua VM on 32 bit hardware is not tested.

Operating system and environment

Development and testing is performed on Linux with GNU toolchain. Various *BSD flavours should also work. In general, Viua VM should be capable of running on any UNIX-like operating system.

Microsoft Windows operating systems are not supported.


Following tools should be available on the system to support compilation and development of the VM.

GNU Make

Build scripts depend on GNU Make.


Valgrind is used to test memory usage and ensure that the machine does not leak.

Python 3

VM's test suite depends on Python 3.


Viua VM uses Git as the version control software.

C++ Compiler

Viua VM requires a reasonably up-to-date C++ compiler supporting C++17. Both GCC (version 7 and later, 6 may also suffice but is no longer tested) and Clang (5 and later) are supported.


Assuming all requirements are met, below steps should give you a working Viua VM.

       ~ ]$ # Clone Viua Git repository, use "devel" branch to get latest code.
       ~ ]$ git clone --recursive --branch devel git://
       ~ ]$ 
       ~ ]$ # Change to the directory containing cloned repository.
       ~ ]$ cd viuavm/
~/viuavm ]$ 
~/viuavm ]$ # Compile the code.
~/viuavm ]$ make
~/viuavm ]$ 
~/viuavm ]$ # Run tests
~/viuavm ]$ # This requires Valgrind and Python 3 to be installed.
~/viuavm ]$ # Tests may take several minutes to finish running, depending on your machine's parameters.
~/viuavm ]$ make test
~/viuavm ]$ 
~/viuavm ]$ # Check version of the VM.
~/viuavm ]$ ./build/bin/vm/kernel --version

"Hello World!"

To honour the decades-old tradition, this is the first program one should write in a new language. Here is how to compile and run the "Hello World!" program on Viua VM.

Source code

Open an editor and copy the code presented below to a file. Lines beginning with -- are comments and may be omitted. Everything else must be copied verbatim.

-- Functions begin with the '.begin:' directive followed by a function name.
-- Function names **must** include the arity.
-- Arity is checked at compile time at the call site.
.function: main/0
    -- Store string in first register of local register set.
    text %1 local "Hello World!"

    -- Print the contents of first register from local register set.
    print %1 local

    -- These two instruction **must** appear at the end of the main/0 function.
    -- This is enforced by the compiler.
    izero %0 local
-- Function definitions are finished using the '.end' directive.

The source code has to be compiled into bytecode before the VM can run it. Assembler is located at ./build/bin/vm/asm, relative to the main repository directory. VM kernel is located at ./build/bin/vm/kernel, relative to the main repository directory.

]$ vi hello_world.asm
# ... paste the code copied from above and save the file ...
]$ ./build/bin/vm/asm hello_world.asm
]$ ./build/bin/vm/kernel a.out
Hello World!

You can run the compiled file through a disassembler. This is an optional step - disassembling is mentioned here for the curious individuals who may be interested in the fact that disassembly capabilities are provided out-of-the-box. In the example below the disassembler is run with some options that make it produce more verbose output.

]$ # The --info option prints additional information the VM can infer from the supplied binary.
]$ # The --with-entry option prints out the source of the special __entry function that is the entry point of Viua VM programs, and
]$ # is generated automatically by the assembler.
]$ ./build/bin/vm/dis --info --with-entry a.out

The resulting output should be similar to the one presented below (assuming you did not modify the example code to print, for example, "Hello Joe!").

-- bytecode size: 78
-- functions:
--   main/0 -> 35 bytes at byte 0
--   __entry -> 43 bytes at byte 35

.function: main/0
    strstore %1 local "Hello World!"
    print %1 local
    izero %0 local

.function: __entry
    ress local
    frame %0 %16
    call %1 local main/0
    move %0 local %1 local