Below is the simple Hello World
program written in New-Assembly.
_ : data
txt $ string = "Hello world"
_ : start
mov tlr , string
mov fdx , 1
syscall 0 , %ios
retn 0
Documentation about newasm
which includes following topics:
- Compiling binaries
- Arguments
- Launch modes
- Sections
- Built-in references
- Instructions
- Procedures
- Exit codes
- Comments
- Interesting examples
- Unassigned references
- Structures
- Project files
- Dynamic libraries
- Environment variables
- Containers and data structures
- Threads
This project is written purely in C++ using its standard libraries, so compiling it should be easy. To download C++ compiler, please follow instructions on the link below:
- There are some arguments you can use when executing the interpreter.
Argument | Parameters | Description |
---|---|---|
-ver |
- | Displays version information only, and doesn't start the interpreter at all. |
-help |
- | Displays help information. |
-input |
<filename> |
Sets the input file; if -input was not provided, interpreter sets it to input.asm . |
-repl |
- | Enter the read-evaluate-print mode. |
-newproj |
- | Create a new project file if one doesn't already exist. |
-tests |
- | Start the test function. |
-log |
- | Toggle the logging system. |
-nover |
- | Turn off version checking. |
-mode |
<id> |
Change the launch mode. |
When running the newasm
executeable, you can optionally use the -mode
argument to open the application in different modes:
- mode 0: this is the default interpreter mode, it just does the primary idea of what it is supposed to do - run the assembly code;
- mode 1: this is the CTL, or control console, mode - application will run as the command prompt with its own commands, you can install packages and maintain your project.
CTL mode brings new different commands with it. Below is a list of available commands:
Command | Arguments | Description |
---|---|---|
help |
- | Displays this panel within the console. |
exit |
- | Closes the application. |
install |
<lib> |
Install a library. |
The install-command allows you to download and install New-ASM dynamic libraries and packages. There are 2 types of downloadable files - dynamic libraries (.newasm_dl
files) and library setups (.newasm_set
files). Setups allow library developers to provide more information about the library itself.
- An example library on the download server:
internettest.newasm_dl
onserver.com/
:
mov fdx , 1
mov tlr , "Hi"
mov stl , %endl
syscall 0 , %ios
zero stl
zero tlr
Example of command usage:
install internettest
Notice how we just provided the library name, and not the extension. This will display the following information:
>>> install internettest
[NewASM] PROGRAM THREAD @ System info | Attempting to install the "internettest" package.
* Progress: [========================================] 100 %
Accessed the download server...
Successfully downloaded the library!
Now, if we want to download a package (or a setup), we use the same command, but the process will be different:
net-conf.newasm_set
on server.com/
:
~setup : msg
Welcome to netconf!
~setup : dlname
netconf
~setup : impl
mov tlr , "INTERNET WORKS!"
mov fdx , 1
mov stl , %endl
syscall 0 , %ios
zero stl
As you can see, we can use setup labels to mark code. Installing this with:
install net-conf
we will receive the following output:
>>> install net-conf
[NewASM] PROGRAM THREAD @ System info | Attempting to install the "net-conf" package.
* Progress: [========================================] 100 %
Accessed the download server...
Successfully downloaded the setup.
Preparing to run the setup...
* Imported the dynamic library name...
* Imported the dynamic library install message...
* Imported the dynamic library implementation...
Successfully finished the setup.
Info: Welcome to netconf!
Sections are built-in "tags" used to classify code. Each section uses different syntax in terms of instructions. General syntax is:
_ : section_name
In this section, you can setup event handlers.
_ : hndl
~exit , MY_EXIT_PROC
_ : start
proc 0 , MY_EXIT_PROC
; code
halt proc , 0
end
; code
Event name | Passed information | Description |
---|---|---|
~exit |
/ | Called when the program ends. |
In this section, you can setup some settings for your program. It is thus recommended to keep this section on top of the code. General syntax is:
_ : config
configuration ~ value_in_specific_datatype
_ : data
; some stuff
_ : start
mov fdx , 100
ret fdx
A simple example would be:
_ : config
memsize ~ 256 ; can be any integer from 1 to 512
Setting name | Data type | Description |
---|---|---|
memsize |
num |
Reallocates the number of addresses for the heap and the stack of the program. |
lazy_evhndlr |
num |
Toggles the "lazy event handler" option on (1) or off (0). If it is turned on, event handlers will not check if procedures they're assigned actually exist. |
In this section, you can declare variables to avoid repeated code. General syntax is:
data_type $ variable_name = variable_value
You can use variable_name
as an operand in instructions documented below.
There are 3 data types:
num
for integers;decm
for floats;txt
for strings;ref
for references to data symbols (basically a kind of a pointer);char
for characters.
In this section, you can perform instructions, and cannot create variables, or else program will end with exit code 1.
This language brings some built-in references, or rather operands, with itself - list:
%ios
- used as an operand insyscall
, represents a module of system calls responsible for input and output streaming;%fs
- used as an operand insyscall
, represents a module of system calls responsible for input and output streaming;%exf
- used as an operand insyscall
, represents a module of system calls responsible for execution flow (starting child processes);%cmanip
- used as an operand insyscall
, represents a module of system calls responsible for container and data structure manipulation;%net
- used as an operand insyscall
, represents a module of system calls responsible for network features;%mem
- used as an operand insyscall
, represents a module of system calls responsible for memory/data management;%endl
- line ending, used instl
;&%null
- used to leave references/pointers unassigned/uninitialized.%nl
- used as a null operand in some instructions.
WARNING: Syntax such as % ios
is invalid.
Below is a list of available instructions. General syntax is:
instruction suffix , operand
Ends your program with specific exit code.
instruction
-retn
suffix
- no suffix, useretn exit_code
operand
- exit code
instruction
-ret
suffix
- register nameoperand
- no operand (0
)
_ : start
retn 23
Output:
[newasm] PROGRAM THREAD @ System info: Program finished with exit code : 23
_ : start
mov tlr , 8
ret tlr
Output:
[newasm] PROGRAM THREAD @ System info: Program finished with exit code : 8
Set value of a specific register.
instruction
-mov
suffix
- register nameoperand
- new register value
instruction
-stor
suffix
- register nameoperand
- variable name
In this example, we basically do fdx=1
:
_ : start
mov fdx , 1
retn 23
In this example, we basically do fdx=1
, myvar=fdx
, exit 1
:
_ : data
num $ myvar = 0
_ : start
mov fdx , 1
stor fdx , myvar
retn myvar
- There are input and output registers. Input registers are used to get the input from the user, and output registers are used to store data which will be used as an argument in a
syscall
or an operand in an instruction.
Register name | Full name | Description |
---|---|---|
fdx |
function index | Holds an index of a function syscall will call. |
tlr |
typeless register | Typeless register (can hold any value, even code literals). Used as an output argument in some syscall s. |
stl |
secondary typeless register | Typeless register; however used to hold built-in operands for syscall s. |
stk |
stack pointer | Points at the top of the stack. |
hea |
heap pointer | Points at an address in the heap. |
psx |
procedure scope exit value | Holds value returned inside a procedure using halt . |
prp |
procedure pointer | Points at the procedure that was called using call . |
cpr |
comparsion result register | Holds a value of the comparsion (cmp ) result; 1 for equal , 2 for less and 3 for greater (although there are 6 logical variants of jmp , only these 3 cases are required and detected by cmp ). |
cr0 |
primary calculation register | Register in which all the calculation results are stored. Read this for more information... |
cr1 |
alternate calculation register | Register which is used as a second operand in calculations. Read this for more information... |
br0 |
primary bit operation register | Register in which all the bitwise calculation results are stored. Read this for more information... |
br1 |
alternate bit operation register | Register which is used as a second operand in bitwise calculations. Read this for more information... |
cpt |
container pointer | Register holding an address specifically of a container or a data structure. Read this for more information... |
Set value of a specific register.
instruction
-syscall
suffix
- no suffixoperand
- no operand
_ : start
mov fdx , 1
mov tlr , "Hello World"
syscall 0 , %ios
retn 23
Module | ID | Arguments | Description |
---|---|---|---|
%ios |
1 |
tlr , stl |
Prints exclusively text. Uses stl as a help argument. |
%ios |
2 |
tlr , stl |
Prints integers and floating point numbers. Uses stl as a help argument. |
%ios |
3 |
- | Requests textual user input and stores the value in tlr . |
%ios |
4 |
- | Requests numeric (including floats) user input and stores the value in tlr . |
%ios |
5 |
tlr |
Prints the textual value of a built-in operand. |
%ios |
6 |
tlr , stl |
Prints the name of a symbol a reference is pointing to. |
%ios |
7 |
tlr , stl |
Prints a single character. |
%ios |
8 |
- | Requests a single character input from the user and stores the value in tlr . |
%fs |
1 |
tlr |
Create a directory; with tlr being a string containing the directory name. |
%fs |
2 |
tlr |
Remove a directory; with tlr being a string containing the directory name. |
%fs |
3 |
tlr |
Create a file; with tlr being a string containing the file name. |
%fs |
4 |
tlr |
Remove a file; with tlr being a string containing the file name. |
%fs |
5 |
tlr , stl |
Overwrite file content; with tlr being a string containing the file name, and stl being a string containing the new content. |
%fs |
6 |
tlr , stl |
Append content to file; with tlr being a string containing the file name, and stl being a string containing the content to append. |
%fs |
7 |
tlr |
Remove all file content; with tlr being a string containing the file name. |
%fs |
8 |
tlr , stl |
Read a file line; with tlr being a string containing the file name, and stl being the line number. Read content is subsequently stored in tlr . |
%exf |
1 |
tlr |
Start a new child process; with tlr being a string containing the file name. |
%cmanip |
1 |
cpt |
Clear the bit array, with cpt being a pointer holding the address of your bit array. |
%cmanip |
2 |
cpt |
Flip the bit array, with cpt being a pointer holding the address of your bit array. |
%cmanip |
3 |
cpt |
Reverse the bit array, with cpt being a pointer holding the address of your bit array. |
%cmanip |
4 |
cpt , tlr , stl |
Set a value at a specific index, with cpt being a pointer holding the address of your bit array, tlr an index and stl either 0 or 1 as a value. |
%cmanip |
5 |
cpt , tlr |
Get value stored at the bit array, with cpt being a pointer holding the address of your bit array and tlr being the index. After the syscall , the function will store the value in tlr . |
%cmanip |
6 |
cpt , tlr , stl |
Set-at-parent-of function, with cpt being a pointer holding the address of your binary tree, tlr being the index and stl the value. |
%cmanip |
7 |
cpt , tlr , stl |
Set-at-right child-of function, with cpt being a pointer holding the address of your binary tree, tlr being the index and stl the value. |
%cmanip |
8 |
cpt , tlr , stl |
Set-at-left child-of function, with cpt being a pointer holding the address of your binary tree, tlr being the index and stl the value. |
%cmanip |
9 |
cpt , tlr , stl |
Get-at function, with cpt being a pointer holding the address of your binary tree and tlr being the index. After the syscall , the function will store the value in tlr . |
%net |
1 |
tlr , stl |
Download a file, with tlr being a link to the file and stl being the output destination. |
%mem |
1 |
tlr |
Marks a variable as a constant, with tlr being a pointer to the specific variable. Trying to modify a variable using stor afterwards will cause errors. |
Do nothing.
instruction
-nop
suffix
- no suffixoperand
- no operand
_ : start
nop
retn 23
Do nothing. NOT RECOMMENDED TO USE!
instruction
-rem
suffix
- no suffixoperand
- your comment
_ : start
rem 0 , "my comment"
retn 23
Ensure that a symbol is available for further use.
instruction
-sysreq
suffix
-proc
,data
operand
- procedure return value
_ : data
_ : start
; Notice how we haven't declared anything in _:data
sysreq data , variable
; Program will be terminated with exit code 4
; Same happens when we try to access a procedure:
sysreq proc , some_random_proc
Return a value inside a function.
instruction
-halt
suffix
-proc
operand
- procedure return value
_ : data
num $ variable = 0
_ : start
proc 0 , testprocedure
halt proc , 364
end
call 0 , testprocedure
stor psx , variable
mov tlr , variable
mov fdx , 1
syscall 0 , %ios
retn 1
- Push and pop values to and from the stack, respectively.
instruction
-push
suffix
- no suffixoperand
- constant value or a value of a variable
instruction
-pop
suffix
- no suffixoperand
- variable to pop the value to
_ : data
num $ myvar2 = 0
_ : start
push 0 , 273
; change myvar2 to something dumb:
stor fdx , myvar2
pop 0 , myvar2
mov tlr , myvar2
mov fdx , 1
syscall 0 , %ios
retn 0
- TIP: If you just want to pop the value off the stack, and not store it anywhere, just do:
_ : start
pop 0 , %nl
Resets the register to an invalid value that cannot be used.
instruction
-zero
suffix
- register nameoperand
- no operand
_ : start
zero stl
; something ?
Move down and up the heap.
instruction
-heap
suffix
- no suffixoperand
- number of addresses to move up to
_ : data
num $ mynum = 0
_ : start
heap 0 , 3
stor hea , mynum
mov tlr , mynum
mov fdx , 2
syscall 0 , %ios
- Load data and store data from the heap and into the heap, respectively.
instruction
-load
suffix
-adr
,ref
operand
- literal value or a reference
_ : data
decm $ testdecimal = 0.0
_ : start
; If the suffix of the LOAD instruction is `adr`,
; then we will update the value in the address heap pointer
; is pointing to - HOWEVER, if the suffix is `ref`, then we will
; store the value in the address heap pointer is pointing to
; into some variable in `_:data`.
load adr , 736.38 ; hea = something
load ref , testdecimal ; myvar = hea
mov tlr , testdecimal
mov stl , %endl
mov fdx , 2
syscall . 0 , %ios
retn 0
Output:
736.38
- If we expand our code, and manually assign addresses before cleaning up the heap, we can do this:
_ : data
decm $ testdecimal = 0.0
decm $ testdecm2 = 0.0
_ : start
load adr , 736.38 ; hea = something
load ref , testdecimal ; myvar = hea
mov tlr , testdecimal
mov stl , %endl
mov fdx , 2
syscall 0 , %ios
; Allocate more space:
heap 0 , 1
load adr , 9821.38 ; hea = smth
load ref , testdecm2 ; myvar = hea
mov tlr , testdecm2
mov stl , %endl
mov fdx , 2
syscall 0 , %ios
mov hea , 0 ; manually access the first address
load ref , testdecm2 ; myvar = hea
mov tlr , testdecm2
mov stl , %endl
mov fdx , 2
syscall 0 , %ios
mov hea , 1 ; manually access the second address
load ref , testdecm2 ; myvar = hea
mov tlr , testdecm2
mov stl , %endl
mov fdx , 2
syscall 0 , %ios
heap 0 , -1 ; let all the memory go to avoid getting the memory leak
Output:
736.38
9821.38
736.38
9821.38
- NOTE: Procedures and variables you create in New-Assembly are not located in the stack and the heap of your program, so you have both the stack and the heap for yourself, which means that addresses in the heap start from 0 and go up by 1. You may ask, why is that - well New-Assembly mimics the assembly language and doesn't need to go by the rules set by the standards.
- You can create labels inside
_:start
and then jump to them using thejmp
instruction. General syntax is:
_ : start
_ ! label_name
; somewhere
jmp 0 , label_name
_ : start
_ ! labelname
mov . fdx , 4
syscall . 0 , %ios
jmp 0 , labelname
A little too complex example.
_ : start
jmp 0 , label2
_ ! label
mov tlr , "label called"
mov fdx , 1
syscall . 0 , %ios
mov fdx , 72
jmp 0 , label3
ret fdx
_ ! label2
mov tlr , "label2 called"
mov fdx , 1
syscall 0 , %ios
jmp 0 , label
_ ! label3
mov tlr , "label3 called"
mov fdx , 1
syscall 0 , %ios
retn 3873
Output:
label2 called
label called
label3 called
[newasm] PROGRAM THREAD @ System info: Program finished with exit code : 3873
Compare values of registers with values stored in the operands.
cmp . fdx , 3 ; check if fdx is 3
According to the result cmp
stores in its own "hidden" register, you can use the following variants of the jmp
instruction in order to perform jumps to labels according to the value of the cpr
(comparsion result register):
Instruction | Processed if... |
---|---|
je |
comparsion returned equal . |
jne |
comparsion returned not equal . |
jl |
comparsion returned less . |
jg |
comparsion returned greater . |
jle |
comparsion returned less or equal . |
jge |
comparsion returned greater or equal . |
_ : start
mov tlr , 5.8
cmp tlr , 1
je 0 , equal
;jne 0, notequal
jl 0 , less
jg 0 , greater
;jle 0 , lesseq
;jge 0 , greatereq
; We just want to check if they are either equal, less or greater.
_ ! equal
mov tlr , "EQUAL"
mov fdx , 1
mov stl , %endl
syscall 0 , %ios
jmp 0 , endtheprogram
_ ! notequal
mov tlr , "NOT EQUAL"
mov fdx , 1
mov stl , %endl
syscall 0 , %ios
jmp 0 , endtheprogram
_ ! less
mov tlr , "LESS"
mov fdx , 1
mov stl , %endl
syscall 0 , %ios
jmp 0 , endtheprogram
_ ! greater
mov tlr , "GREATER"
mov fdx , 1
mov stl , %endl
syscall 0 , %ios
jmp 0 , endtheprogram
_ ! lesseq
mov tlr , "LESS OR EQUAL"
mov fdx , 1
mov stl , %endl
syscall 0 , %ios
jmp 0 , endtheprogram
_ ! greatereq
mov tlr , "GREATER OR EQUAL"
mov fdx , 1
mov stl , %endl
syscall 0 , %ios
jmp 0 , endtheprogram
_ ! endtheprogram
retn 0
Output:
GREATER
There are 6 mathematical instructions you can use:
add
- addition,sub
- subtraction,mul
- multiplication,div
- division,exp
- exponentiation,log
- logarithm.
All of these operations use cr0
and cr1
registers. The result is stored in cr0
; so:
_ : start
mov cr0 , 3.0 ; can be either a float or a whole number
mov cr1 , 9 ; same
add ; cr0 = cr0 + cr1
sub ; cr0 = cr0 - cr1
mul ; cr0 = cr0 * cr1
div ; cr0 = cr0 / cr1
exp ; cr0 = power(cr0,cr1)
log ; cr0 = log_c1(cr0)
There are 6 bitwise operations you can use:
and
- and,or
- or,not
- not,xor
- exclusive or,shl
- shift left,shr
- shift right.
All of these operations use br0
and br1
registers. The result is stored in br0
; so:
_ : start
mov br0 , 1 ; must be a number
mov br1 , 1 ; same
and ; br0 = br0 & br1
or ; br0 = br0 | br1
not ; br0 = ~br1
xor ; br0 = br0 ^ br1
shl ; br0 = br0 << br1
shr ; br0 = br0 >> br1
These instructions are used to increment or decrement register values. Since registers can be of various types, these 2 instructions perform differently.
inc register_name
dec register_name
If you operate on a whole number or rational number register, then it may not be so interesting, it just increments it by 1.
inc br0 ; br0++
dec cr1 ; cr1--
If you are operating on a typeless register, these operations will check if the register is holding a whole number, and then apply changes to it. Namely, if you try to increment tlr
while tlr
is holding a string, you will get a data type mismatch exception.
However, what if you try to decrement a symbol reference, well - this gets interesting. For instance, if you tried to decrement the prp
register (which is a reference to a last used procedure), you can't just decrement it by 1 since it is internally pointing to a pair in the procedure map, so the interpreter does the work for you and updates it to the pair before the pair prp
is pointing at.
Demonstration:
_ : data
ref $ temporary = &%null
_ : start
proc 0 , procedure_1
halt proc , 0
end
proc 0 , procedure_2
halt proc , 0
end
proc 0 , procedure_3
halt proc , 0
end
mov prp , &procedure_1
inc prp
stor prp , temporary
mov tlr , temporary
mov stl , %endl
mov fdx , 6
syscall 0 , %ios
mov prp , &procedure_3
dec prp
stor prp , temporary
mov tlr , temporary
mov stl , %endl
mov fdx , 6
syscall 0 , %ios
Output:
procedure_2
procedure_2
- A little instruction used to debug register values. Example:
_ : start
; ... some code
db tlr
Output:
[NewASM] PROGRAM THREAD @ Debug | tlr = `"string"`
Procedures allow you to use the same piece of code without having to actually repeat it. General syntax is:
proc 0 , procedure_name
; code
end
To call the procedure, use:
call 0 , procedure_name
- Here is an example:
_ : start
proc 0 , test
halt proc , 1
end
call 0 , test
retn 0
Basically, these are just functions, but in assembly.
When a fatal error happens, program will shut down, returning a specific exit code, below is a list of exit codes.
Exit code | Description |
---|---|
0 |
No termination point (standard exit code if you have no ret or retn in your script). |
1 |
Invalid section (for example, tried to enter a section named _:lol ). |
2 |
Attempted to call a procedure which does not exist. |
3 |
Invalid non-numeric value was passed to retn . |
4 |
sysreq failed, pretty self-explanatory. |
5 |
Stack/heap collision; pretty self-explanatory. |
6 |
Data overflow - tried to pop a value into unallocated address. |
7 |
Data type mismatch. |
8 |
Tried to redefine a label. |
9 |
Bus error; tried to access an invalid label with jmp . |
10 |
Invalid instruction; pretty self-explanatory, also happens if you use . or , (instruction parsing delimiters) in your rem comments. |
11 |
Memory overflow. |
12 |
Memory underflow. |
13 |
Procedure redefinition. |
14 |
Invalid memory access; tried to access an address using mov.hea,... that isn't allocated for the heap. |
15 |
Invalid syntax. |
16 |
Memory leak: neither retn , ret or heap were used at the end of the program while the hea register wasn't at 0. |
17 |
Invalid configuration. |
18 |
You tried to call a procedure within a procedure. |
19 |
Unknown system call index (invalid value moved into fdx ). |
20 |
Tried to create a child process in a child process. |
21 |
Tried to jump to a label in a child process. |
22 |
Attempted to use an unassigned pointer/reference variable. |
23 |
Tried to redefine a variable. |
24 |
Tried to redefine a structure. |
25 |
Unexpected closing brace. |
26 |
Tried to access a structure that hasn't been declared. |
27 |
Tried to access an undefined structure member. |
28 |
Tried to create a struct inside a struct. |
29 |
Expected closing brace. |
30 |
Tried to create an empty procedure. |
31 |
Tried to redefine a data structure. |
32 |
Unexpected usage of the end instruction. |
33 |
Tried to use an improperly loaded dynamic library instruction. |
34 |
Unknown event specified in the handler section. |
35 |
Assigned an invalid procedure as an event handler. |
36 |
Tried to modify a constant. |
37 |
Operating system-related error. |
Comments are also available:
_ : start
; comment
mov fdx , 1
mov tlr , "hello" ; comment
syscall 0 , %ios ; comment again
Below is a list of interesting examples of using the language.
_ : start
mov fdx, 3
mov tlr, "filename"
syscall . 0, %fs
mov stl, "TEXTeee"
mov fdx, 6
syscall 0, %fs
mov stl, 1
mov fdx, 8
syscall . 0, %fs
mov stl, %endl
mov fdx, 1
syscall 0, %ios
retn 0
Output:
TEXTeee
index.nax
:
_ : start
mov tlr, "child.nax" ; another nax file containing stuff such as config modifications, variables and procedures
mov fdx, 1
syscall 0 , %exf ; create a process and execute it
mov tlr , "Hi after the process" ; this line will be processed AFTER child.nax finishes executing
mov stl , %endl
mov fdx , 1
syscall 0 , %ios
retn 0
child.nax
:
_ : data
num $ mynum = 0
_ : start
heap 0 , 36
stor hea , mynum
mov tlr , mynum
mov fdx , 2
syscall 0 , %ios ; prints heap size (36)
heap 0 , -36 ; free up memory we occupied for the sake of the example
Output:
36
Hi after the process
- You cannot create labels and jump to them in child processes.
- If you use
ret
orretn
inside a child process, it will terminate the whole program with that exit code and not just the child process. - Procedures and variables created inside the child process can be used in the parent process (in our case
index.nax
) after the child process finishes executing.
_:data
ref $ unassigned_pointer = &%null
This reference is left unassigned and an attempt to use it will result in an exception.
In this quite frankly low-level language, there are also structs! General syntax is:
_:data
struct $ structure_name = {
; members
data_type $ member_name = member_value
}
_ : data
struct $ mystruct = {
num $ lol = 98
decm $ decimal = 2.3
txt $ text = "hi from struct"
}
struct $ mystruct2 = {
num $ lol = 45
decm $ decimal = 833.4
txt $ text = "hi from struct again"
ref $ reference = &prptest
}
_ : start
mov tlr , text @ mystruct
mov stl , %endl
mov fdx , 1
syscall 0 , %ios
mov tlr , decimal @ mystruct
mov fdx , 2
syscall 0 , %ios
mov tlr , lol @ mystruct
mov fdx , 2
syscall 0 , %ios
mov tlr , text @ mystruct2
mov stl , %endl
mov fdx , 1
syscall 0 , %ios
mov tlr , decimal @ mystruct2
mov fdx , 2
syscall 0 , %ios
mov tlr , lol @ mystruct2
mov fdx , 2
syscall 0 , %ios
mov tlr , reference @ mystruct2
mov fdx , 6
syscall 0 , %ios
mov stl , 45657
stor stl , lol @ mystruct2
mov tlr , lol @ mystruct2
mov fdx , 2
mov stl , %endl
syscall 0 , %ios
mov psx , "HIII243"
stor psx , text @ mystruct
mov tlr , text @ mystruct
mov fdx , 1
mov stl , %endl
syscall 0 , %ios
Output:
hi from struct
2.3
98
hi from struct again
833.4
45
prptest
45657
HIII243
- Currently, if you want to store a value into a struct member, only the
stor
instruction will work - note that instructions such asload
andpop
will not work regarding this. - This syntax is a must:
struct $ name = { ; brace must be HERE
; and not here
num $ number = 384
}
Project files (.newasm_proj
file) are files that define information about your New-ASM project. General name format for them is:
<entry file name>.newasm_proj
For example, if my -input
file is input.asm
, project file for that would be input.asm.newasm_proj
. This is basically an INI file.
Key name | Description |
---|---|
name |
Name for your project. |
version |
Version of your project. |
dlibs |
Dynamic libraries your project is using. |
Example index.asm.newasm_proj
file:
name = Unnamed project
version = 0.0.1
dlibs = testlib, sayhi
Dynamic libraries (.newasm_dl
file) are files that provide user-made instructions. For example, let's say this is a NewASM dynamic library you wrote:
sayhi.newasm_dl
:
mov tlr , "hi from my dynamic library"
mov fdx , 1
syscall 0 , %ios
In your entry file - index.asm
, you can do this:
_ : start
mov tlr , "some stuff"
inc prp ; bunch of operations
; more stuff...
sayhi ; your very own custom instruction
This is literally a fancy way of making procedures, making them reusable across files, however there are limits:
- You cannot create labels.
- You thus cannot use jump instructions such as
jmp
,je
,jne
and more.
If you make an error inside a dynamic library, you will get a runtime error while the library was getting implemented. Below is a list of runtime errors that may occur:
Runtime error code | Description |
---|---|
1 |
Tried to create a label. |
2 |
Tried to use an unsupported instruction. |
Environment variables are typeless variables that are defined within the .newasm/env_vars.ini
file. Let's take a look:
.newasm/env_vars.ini
:
testenv = "hello from env var"
index.asm
:
_ : start
mov tlr , * / testenv
mov fdx , 1
syscall 0 , %ios
- NOTE: You must use
*/
before the environment variable name so the program knows you are using an environment variable and not a standard variable, which means this wouldn't work:
_ : start
mov tlr , testenv
mov fdx , 1
syscall 0 , %ios
- There are following data structures and containers available:
- Bit arrays
- Binary trees
- Arrays of bits. Internally, they are just integers, but you are provided
syscall
s to manipulate them as if they were really just arrays of bits, an example:
index.asm
:
_ : data
bit_arr $ testbitarr = 0
_ : start
mov cpt , &testbitarr
mov tlr , 2
mov stl , 1
mov fdx , 4
syscall 0 , %cmanip
mov tlr , 1
mov fdx , 5
syscall 0 , %cmanip
mov fdx , 2
mov stl , %endl
syscall 0 , %ios
mov tlr , 2
mov fdx , 5
syscall 0 , %cmanip
mov fdx , 2
syscall 0 , %ios
Output:
0
1
- NOTE: To really understand what's going on, check out the list of available system calls.
- Binary trees are specific arrays containing the parent nodes which have their right and their left child. Example:
index.asm
:
_:data
bin_tree $ testbintree = 0
_:start
mov cpt , &testbintree
mov tlr , 0
mov stl , 33
mov fdx , 7
syscall . 0 , %cmanip
mov tlr , 0
mov fdx , 9
syscall 0 , %cmanip
mov stl , %endl
mov fdx , 2
syscall 0 , %ios
mov tlr , 1
mov fdx , 9
syscall 0 , %cmanip
mov stl , %endl
mov fdx , 2
syscall 0 , %ios
mov tlr , 2
mov fdx , 9
syscall 0 , %cmanip
mov stl , %endl
mov fdx , 2
syscall 0 , %ios
mov tlr , 3
mov fdx , 9
syscall 0 , %cmanip
mov stl , %endl
mov fdx , 2
syscall 0 , %ios
Output:
-1
33
0
0
Threads are blocks of code declared within the data
section. Once you switch to the start
section, they will start executing simultaneously with the source code.
Threads are declared like this:
_ : data
thread $ test_thread = {
; code
}
_ : start
; more code
; "code" and "more code" will be executed almost at same time.
Since this is a low-level language, there is not much of use of these threads yet.
Example:
index.asm
:
_ : config
memsize ~ 87
_ : data
txt $ mytext = "Hello World"
thread $ testthread = {
__say 0,"thread debug 1"
__say 0,"thread debug 3"
__say 0,"thread debug 5"
__say 0,"thread debug 6"
__say 0,"thread debug 7"
__say 0,"thread debug 8"
__say 0,"thread debug 9"
__say 0,"thread debug 10"
}
thread $ testthread2 = {
__say 0,"thread debug 2"
__say 0,"thread debug 4"
}
_ : start
zero stl
mov tlr , mytext
mov fdx , 1
syscall 0 , %ios
;other code
Output will be:
thread debug 1
thread debug 2
thread debug 3
thread debug 4
thread debug 5
thread debug 6
thread debug 7
thread debug 8
thread debug 9
Hello World thread debug 10