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 name instruction instruction [[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. DIRECTIVES Sections 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 type value 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. INSTRUCTIONS Environment and diagnostic Arithmetic Bit operations Flow control I/O Register operations Concurrency Constructors Memory operations FILES .s, .asm By convention, the files containing Viua assembly language source code have either .s or .asm suffix. EXAMPLE Minimal 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 ALSO viua-asm(1), viua-ld(1). elf(5). Levine, John R. Linkers and Loaders. Academic Press, 2000. ISBN 978-15-5860-496-4 Patterson, David A. and Waterman, Andrew. The RISC-V Reader. Strawberry Canyon LLC, 2017. ISBN 978-09-9924-911-6 Web site ‹https://viuavm.org› Source code repository ‹https://git.sr.ht/~maelkum/viuavmVIUA VM Part of the viua(1) toolchain.