summaryrefslogtreecommitdiff
diff options
authorMarek Marecki <[email protected]>2023-10-09 22:50:19 +0200
committerMarek Marecki <[email protected]>2023-10-09 23:54:11 +0200
commit4d6823b86f793e445b6be4af561e77010ff42e0a (patch)
tree756da09520bc56a0736b731762360e37c5ecb924
parent90afc70cf88a9764f94d88145e5b585219087595 (diff)
downloadviuavm-master.tar.gz
Release 0.13HEADv0.13.0master
The assembly language was reworked "a wee bit". By this I mean that the source files will have to be almost completely rewritten, as there are new ways of: - storing objects in .rodata - loading data from .rodata into working memory - declaring and defining functions - jumps Basically everything changed, except for the syntax of instructions. SECTIONS The assembler no longer switches sections automatically to put objects and code in appropriate sections. It now requires explicitly setting the active section with .section ".rodata" .section ".text" The only two valid names are ".rodata" and ".text". ALLOCATING OBJECTS IN .rodata To allocate an atom or a string in .rodata use the following code: .section ".rodata" .label your_label .object string "Hello, World!" Both atoms and strings are stored the same way so allocate them as strings. They require different ways of loading into memory, though. Atom is one of the fundamental types, and as such has a dedicated instruction. To load an atom from .rodata use the reference syntax: atom $1.l, @your_label To load an atom without an explicit address you can just put it directly in the immediate operand: atom $1.l, atomic_atom Loading a string is a more involved process, and requires copying the data manually between .rodata and working memory. For an example see one of the memcpy(3) and memset(3) tests: - tests/asm/memcpy.asm - tests/asm/memcmp_{eq,gt,lt}.asm as well as the implementations of these functions to see how the data is actually shuffled from place to place: - tests/std/memcpy.asm - tests/std/memcmp.asm There is also an implementation of memset(3) in "tests/asm/memset.asm". The most important thing to note is that when you load the address of a string using ARODP you get the address of the string itself. Subtract 8 bytes from that address, and you will get the address of the 64-bit unsigned integer which stores the size of the string. Then use these two pieces of information to access the string. SYMBOLS, LABELS, AND VISIBILITY All labels (the .label directives) are stored in the symbol table with a few attributes: - type of the symbol they are refering to (either a function STT_FUNC; or an object STT_OBJECT) - binding (global STB_GLOBAL, or local STB_LOCAL) - visibility (default STV_DEFAULT, or hidden STV_HIDDEN) Not all options provided by the ELF standard are used. See elf(5) for more information about types, binding, and visibility. TEXT SYMBOLS: JUMPS A label defined without a corresponding symbol: .label foo_jmp will be STB_LOCAL and STV_HIDDEN. This means that it is only available inside the current compilation unit (ie, the assembly file where it is defined). They could have been defined using visibility STV_DEFAULT but STV_HIDDEN is used to mark them as not callable. Such labels can only be used as targets in the IF instruction: if void, foo_jmp TEXT SYMBOLS: FUNCTIONS To make a callable label (in effect marking it as an entry point of a function) declare a symbol for it explicitly: .symbol foo_global_fn .label foo_global_fn This default combination makes the "foo_global_fn" label STB_GLOBAL and STV_DEFAULT ie, a global function available to all modules which will link to the module in which this symbol was defined. To create a function visible only in the current compilation unit (which would be equivalent to declaring it static in C, or defining it in an anonymous namespace in C++) use: .symbol [[local]] foo_unit_fn .label foo_unit_fn This makes the "foo_unit_fn" function STB_LOCAL and STV_DEFAULT ie, available in the current compilation unit, but not outside of it. To create a function that will be available inside a module, but not globally use: .symbol [[hidden]] foo_module_fn .label foo_module_fn The "foo_module_fn" function is STB_GLOBAL and STV_HIDDEN. What is the purpose of this weird combination? To make the function available outside of the current compilation module, but only until it is first linked to. This allows creating "modules" composed of several compilation units, which have some public and some private functions. The linker will change STB_GLOBAL and STV_HIDDEN into STB_LOCAL and STV_DEFAULT during first linking, making the "global but hidden" symbol local to the resulting ELF. This means that when creating a module from several compilation units it is wise to postpone linking as much as possible, and the way to go is usually to link all individual parts in one go. For example ]$ viua-ld -c -o module.o \ module.fn_a.o module.fn_b.o will yield the expected result, but linking in two steps will probably not. Of course, "modules" defined this way are just a convention. There are other shortcomins to the simplistic scheme outlined above. Duplicate symbols will cause conflicts even if defined as private to a module. However, this should not be problematic as the compilers for high level languages (or assembly programmers themselves) should prefix even private labels with the module's name. While a crude solution, prefixing will solve the problem of name clashes.
-rw-r--r--VERSION2
1 files changed, 1 insertions, 1 deletions
diff --git a/VERSION b/VERSION
index c43e1055f..f3040840f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.12
+0.13