These instructions are used to manually allocate memory on the heap and use it. This article includes the following instructions:
Easily manage heap memory. Example:
.start
heap 40
db hea
malloc 2 ; for test purposes
mov hea, 2
db hea
free nil
db hea
__say 0,"2nd malloc"
malloc 2 ; allocate 2 more spaces in the heap
mov hea, [1] ; using brackets we can access the address id of the malloc-allocated heap
db hea
free nil ; automatically get rid of that allocated memory
db hea
heap -40 ; free up the rest we occupied for some testingOutput:
[NewASM] PROGRAM THREAD @ Debug | hea = `40`
[NewASM] PROGRAM THREAD @ Debug | hea = `2`
[NewASM] PROGRAM THREAD @ Debug | hea = `40`
2nd malloc
[NewASM] PROGRAM THREAD @ Debug | hea = `42`
[NewASM] PROGRAM THREAD @ Debug | hea = `40`
To select what block we want to manipulate, we use sel:
.data
intg alloc: 0
.start
malloc 4 ; 4 bytes + 4 byte header
mov &alloc, *tlr ; tlr has the address of the header
; now we use the `alloc` variable to manipulate the allocated memory
; `sel` to select it
; `free` to free it
sel alloc
mov hea, [0]
; do smth
free allocYou can save data and load data from the virtual memory. Virtual memory behaves differently from the heap and the stack. In order to allocate a specific amount of cells in the virtual memory, use malloc:
malloc 27_ ; use the _ operator to tell malloc to REALLOCATE number of cells in the virtual memory
vmov {4}, "Hello" ; in the new vmov instruction we can modify this memory
cast string ; tell the interpreter to read a string
mov tlr, {4} ; using the {} operator we access the data inside the virtual memory
malloc 0_ ; we can free the memory manually, but not really needed since the program does that for usSuper fun! Using movaddr you can manually set the address of a specific variable.
Warning
The del instruction is more documented in union-related documentation.
.data
string toBeDeleted : "hello"
./funny
intg deletedNumber : 89
./!funny
.start
mov tlr, toBeDeleted
mov stl, 0c1
sysenter "ios"
mov fdx, 1
syscall
del &toBeDeleted ; delete the mem block it is pointin' to
del &funny::deletedNumber
malloc 64
mov hea, [0]
mov imm, 1
load "Hello from crazy var!"
; mov imm, 2
;load &toBeDeleted ; seg fault, we're writing to a memory block we marked as deleted
movaddr &toBeDeleted, *hea ; correct
mov tlr, toBeDeleted
mov stl, 0c1
sysenter "ios"
mov fdx, 1
syscall
heap 21 ; 16 chars in a string and 4 bytes for a header and 1 byte for a new var
; if we had done "heap 20" it would
; modify the variable before it,
; but we would not get any error
; since it is valid code
mov imm, 1
load 72345
movaddr &funny::deletedNumber, *hea
mov tlr, funny::deletedNumber
mov stl, 0c1
mov fdx, 2
syscall
mov tlr, toBeDeleted
mov stl, 0c1
sysenter "ios"
mov fdx, 1
syscall
freeOutput:
Hello from crazy var!
72345
Hello from crazy var!
You can also change the pointer a member of a tuple is holding, with lea and movasx:
lea &tuple, index
del &tuple
lea &tuple, index
movasx &tuple, *hea ; specific addrUsed for merging contexts.
Caution
This instruction was added in build 32.
You use this instruction to ask the VM to dedicate n-number of bytes to a specific thread and use it as stack space.
.text
thread myThread -> {
resb 64 ; ask the system for 64 bytes of thread-safe stack space
push 429
push 'c'
push 873.45
}
Now, 64 bytes of stack space we got from the VM is just a part of the heap, but it is internally used as stack space since each thread has its own copy of the stack pointer because of the context-switching.
You can also use the stack instruction, the JIT compiler replaces standard push, pop and stack with thread-specialized versions. That means you can call procedures that accept arguments. This approach ensures memory thread-safety and speed.
You can still have access to the global stack from within the child procedures and encapsulated lambda procedures.