VIUA-ASM(5) Viua VM Manual VIUA-ASM(5)
NAME
viua-asm - Viua VM assembly language reference
SYNOPSIS.section name.symbol name.symbol [[attributes]] name.label nameinstructioninstruction [[attributes]] argument...
DESCRIPTION
Viua assembly language is used to compose the source code of programs
to be executed by the Viua virtual machine. The language consists of
directives and instructions; the former directing the assembler, and
the latter being encoded into the binary form that, after further pro‐
cessing by viua-ld(1), the virtual machine can understand.
DIRECTIVESSections
The ELF files consist of sections and segments, each holding a specific
part of a program. To control where a portion of the source code will
be put, Viua assembly language uses
.section name
The above line puts subsequent symbols in section name. For example:
.section ".text"
.text ; shortcut for switching to the .text section
would put information in section .text, and
.section ".rodata"
.rodata ; shortcut for switching to the .rodata section
in section .rodata.
Other sections are currently not used by the virtual machine, and will
be rejected if the assembler encounters them.
Symbols and labels
The .symbol and .label directives control binding and visibility of
things declared or defined in a source code file. To learn more about
what binding and visibility mean, refer to the elf(5) man page.
Labels MUST be used right above a definition of an object or a func‐
tion. They point at a location in memory.
Symbols are declarations of entities found in a compilation unit.
┌───────────┬─────────────┬───────────────────────────────────────────┐
│ directive │ meaning │ comment │
├───────────┼─────────────┼───────────────────────────────────────────┤
│ .label │ definition │ points at a location in memory │
├───────────┼─────────────┼───────────────────────────────────────────┤
│ .symbol │ declaration │ controls binding and visibility │
└───────────┴─────────────┴───────────────────────────────────────────┘
All labels are put into the .symtab section to make disassembler's out‐
put more useful. By default, both have local binding but differ in vis‐
ibility: objects have default visibility, functions are hidden.
; local binding and default visibility
.section ".rodata"
.label obj
; local binding and hidden visibility
.section ".text"
.label jmp
If both a .symbol and a .label are given for a name, the .symbol MUST
be the first to appear. Presence of a .symbol affects the default bind‐ing and visibility of functions:
; local binding and default visibility
; (same as with just a .label)
.section ".rodata"
.symbol obj
.label obj
; global binding and default visibility
.section ".text"
.symbol fun
.label fun
The default binding and visibility can be changed by setting attributes
on a .symbol:
┌───────────┬────────────┬────────────────────────────────────────────┐
│ attribute │ ELF │ meaning │
├───────────┼────────────┼────────────────────────────────────────────┤
│ local │ STB_LOCAL │ set binding to local │
├───────────┼────────────┼────────────────────────────────────────────┤
│ global │ STB_GLOBAL │ set binding to global │
├───────────┼────────────┼────────────────────────────────────────────┤
│ hidden │ STV_HIDDEN │ set visibility to hidden │
└───────────┴────────────┴────────────────────────────────────────────┘
Objects CANNOT be be STB_GLOBAL and STV_DEFAULT: Viua does not allow
objects to be visible outside of the compilation unit they were defined
in. This means, that the only valid combinations of binding and visi‐bility for objects are:
• STB_LOCAL and STV_DEFAULT (or STV_HIDDEN): object only visible in
the current file
• STB_GLOBAL and STV_HIDDEN: object defined in one file, but intended
to be used in a different file—during first linking such
global–but–hidden objects are converted to STB_LOCAL and STV_DE‐FAULT (this behaviour is useful when assembling modules from sev‐
eral different compilation units)
Further discussion is only concerned with functions ie, with symbols
and labels pointing into .text section.
STB_LOCAL|STV_HIDDEN
A non–callable jump label.
.label jmp
; or
.symbol [[local,hidden]] x
.label jmp
A name only visible within the current compilation unit.
Such addresses are NOT CALLABLE. The assembler will reject using them
as targets of call instruction, and will report any such occurrence as
an error. They can be used as targets of if instructions.
STB_LOCAL|STV_DEFAULT
A function private to a compilation unit.
.symbol [[local]] x
.label fun
A name only visible within the current compilation unit.
Such addresses are CALLABLE. The assembler will reject using them as
targets of if instructions, and will report any such occurrence as an
error.
STB_GLOBAL|STV_HIDDEN
A function private to a module ie, a few compilation units linked to‐
gether.
.symbol [[hidden]] x
.label jmp
; or
.symbol [[global,hidden]] x
.label jmp
A name visible in other compilation units, but will be converted to
STB_LOCAL and STV_DEFAULT after first linking.
Such addresses are NOT CALLABLE. The assembler will reject using them
as targets of call instruction, and will report any such occurrence as
an error. They can be used as targets of if instructions.
STB_GLOBAL|STV_DEFAULT
A public function.
.symbol x
.label fun
; or
.symbol [[global]] x
.label fun
A name visible in other compilation units.
Such addresses are CALLABLE. The assembler will reject using them as
targets of if instructions, and will report any such occurrence as an
error.
External symbols
These are symbols defined in other compilation units and modules. They
are declared to inform the assembler that such a symbol exists and will
be made available during linking, in order to prevent the assembler
from reporting an error due to use of an undeclared symbol.
.symbol [[extern]] "std::memcpy"
In the example above, an external symbol for the std::memcpy function
is declared. No additional attributes may be defined on an external
symbol.
Unless a symbol is marked with the extern attribute it MUST be defined
within the compilation unit where it is defined. If a .symbol is pro‐
vided ie, a declaration is made, a matching .label must also be pro‐
vided; otherwise, the assembler will report an error.
Objects
Objects are placed in the .rodata section using the .object directive.
For example
.section ".rodata"
.object string "Hello, World!"
will allocate an object of type string in the .rodata section. By de‐
fault, objects are anonymous, but a .label directive—possibly combined
with a .symbol directive—can be used to assign a name to the address
under which the labelled object has been allocated.
A fuller example would therefore be
.section ".rodata"
.label hello_world
.object string "Hello, World!"
The syntax of the .object directive is:
.object typevalue
where type names one of the type recognised by Viua VM, and value is a
valid constructor for objects of type type.
The following types are recognised by the VM:
┌────────┬────────────────────────────────────────────────────────────┐
│ string │ a size–prefixed (using a 64–bit unsigned integer) byte se‐ │
│ │ quence │
└────────┴────────────────────────────────────────────────────────────┘
string.object string ctor...
ctor := "..."
|= uint * "..."
All ctor values are concatendated before the string is stored into the
.rodata section. For example, the following constructor may be used to
allocate the string "Hello, World!":
"He" 2 * "l" "o, W" "orld!"
To allocate "Scooby Doo", one could use:
"Sc" 2 * "o" "by D" 2 * "o"
The strings are size–prefixed, and are NOT null–terminated. The size of
the string is stored immediately before the string's contents as a lit‐
tle–endian 64–bit unsigned integer.
If a label has been assigned to the string, it will point to the con‐tents of the string, not its size. To obtain the size of the string
named some_string one would use the following code (see the source code
in the tests/asm/io_print.asm file to get a complete example):
; LOAD ADDRESS OF THE STRING
; Load the address of the string into a register.
arodp $1.l, @some_string
; LOAD SIZE OF THE STRING
; Load a -8 into another register.
li $2.l, -8
; Then add the -8 to the address of the string's content, to
; get the address of the string's size.
add $2.l, $1.l, $2.l
; Load the doubleword under that address.
ld $2.l, $2.l, 0
; Cast the raw data into an unsigned integer.
cast $2.l, uint
Functions and jump targets
Functions and jump targets are labels pointing into the .text section.
By convention, a label should be put at the beginning of a function,
but it can be put anywhere—the .text section is just a simple array of
instructions, and labels are just recorded offsets in it.
As explained in section Symbols and labels, a .text label is, by de‐
fault, local and not callable. It is only suitable as a jump target:
.label jmp
To mark it as a callable address you have to change its binding to
global, by attaching a .symbol directive to the .label:
.symbol fn
.label fn
Unless additional attributes are set on the .symbol, this will record a
function address.
An entry point into an executable ie, its main function, is identified
by presence of the entry_point attribute (and, by convention, should be
called "main"):
.symbol [[entry_point]] main
.label main
When the output of the linker is requested to be an executable (and not
a library), the linker will report an error if either no function is
marked with the entry_point attribute, or multiple functions are marked
with it. There may be ONLY ONE entry point in the final ELF produced by
the Viua toolchain.
INSTRUCTIONSEnvironment and diagnosticArithmeticBit operationsFlow controlI/ORegister operationsConcurrencyConstructorsMemory operationsFILES.s, .asm
By convention, the files containing Viua assembly language source
code have either .s or .asm suffix.
EXAMPLEMinimal valid program
The smallest valid program is the program that does nothing: it just
returns.
.section ".text"
.symbol [[entry_point]] main
.label main
return
The above snippet shows what does the smallest valid program in Viua
look like. Assuming you saved it in a file called x.s, it can be assem‐
bled, linked, and executed like this:
]$ viua asm x.s
]$ viua ld x.o
]$ viua vm a.out
Or, making the defaults explicit:
]$ viua asm -o x.o x.s
]$ viua ld --type exec -o a.out x.o
]$ viua vm a.out
SEE ALSOviua-asm(1), viua-ld(1).
elf(5).
Levine, John R. LinkersandLoaders. Academic Press, 2000.
ISBN 978-15-5860-496-4
Patterson, David A. and Waterman, Andrew. TheRISC-VReader. Strawberry
Canyon LLC, 2017.
ISBN 978-09-9924-911-6
Web site
‹https://viuavm.org›
Source code repository
‹https://git.sr.ht/~maelkum/viuavm›
VIUA VM
Part of the viua(1) toolchain.