#NewASM

279 messages · Page 1 of 1 (latest)

blissful galleon
#

NewASM Virtual Machine – simulates a computer with its own complex assembly language and compiler; NewASM is a low-level programming language which combines explicit memory and register control, giving it a breeze of assembly-like feel, with high-level functionalities such as objects, threads with many functionalities and many more.
Aim is to create a sealed development environment used for creating platform-independent applications!

https://github.com/bracesoftware/newasm

GitHub

💻 • NewASM is a low-level programming language which combines explicit memory and register control, giving it a breeze of assembly-like feel, with high-level functionalities such as objects, thread...

#

I will do the doc rework since a lot of examples have old syntax

nimble adder
#

🔥

blissful galleon
#

New major update with many many features.
Prone to bugs!

blissful galleon
#

Added namespaces and I/O ports for the virtual disk!

#

Includes optimisation and bug-fixes under the hood

blissful galleon
#

Added tuples and bug fixes

blissful galleon
#
  • Boosted performance with inlined bytecode compiler
  • Added the register dereferencing operator
    Drop a star if you like the project 🖤 :D
cinder veldt
#

interpreting asm? why someone would use that, if it creates a layer of abstraction?

blissful galleon
#
  • Added thread channels.
  • Syntax rework.
blissful galleon
# cinder veldt interpreting asm? why someone would use that, if it creates a layer of abstracti...

Well, abstraction is something relative. What is abstract on our CPUs, cannot be abstract on a virtual machine.

My goal was to make a low level assembly-like language that could be written only once and ran on any machine through the virtual machine and the shell.

The only big abstractions are namespaces, lambda procedures and objects.

But since this is a VM emulating a complex virtual CPU architecture, we cannot call these abstractions as NewASM is supposed to be the “machine code” of its own VM :D

#

My second project goal was to create a C compiler that compiles C code into NewASM code.

So technically, NewASM would essentially become a little platform.

#

As you can see, the VM can run on any Linux or Windows version (I tested it on Vista too), seamlessly, so you can basically look at it as a platform-independent standard for assembly

#

So yeah, this is my reasoning

Please note that the system is currently under heavy development, and that many things are actually prototypes

In build 7 I’ll do a complete memory rework and implement C-like types, allocation and real pointers!

blissful galleon
#

Complete backend rework

#

C-like memory

#

New tcp and http kernel modules

#

Give a star if you find the project interesting! :D

manic flicker
#

it's an assembly language that's interpreted?

blissful galleon
#

but the docs are very outdated

#

at this scale, it is now a vm with its own crazy hardware implementations

manic flicker
#

hardware implementation?

blissful galleon
#

simulation*

manic flicker
#

hardware simulation? that just sounds like a VM

blissful galleon
#

it is a vk

#

vm

manic flicker
#

so it has nothing to do with hardware

blissful galleon
#

not right now

#

but i could do something

manic flicker
#

like what

blissful galleon
#

idk

#

💩

manic flicker
#

lol

blissful galleon
#

so yh

#

something like a hybrid between asm and C

#

so im simplifying the old complex syntax it had

blissful galleon
waxen dune
#

how fast is it on a 'Hello World' program?

blissful galleon
#

fast enough?

#

probably a small part of a millisecond

#

it was doing some tests with python

#

so it is pretty comparable

#

it depends on what you are doing

waxen dune
waxen dune
blissful galleon
blissful galleon
blissful galleon
waxen dune
#

1ms ? or 10ms ?

blissful galleon
#

0.1 ms or smth

#

it doesnt take long to print a string

manic flicker
#

hello world is a bad benchmark

waxen dune
blissful galleon
#

you saw the readme right?

waxen dune
#

bro

#
using "ios"
.data
    string text : "Hello world"
    intg len : $-text
.start
    mov tlr, text
    mov stl, 0c1
    mov fdx, 1
    mov bos, len

    sysenter "ios"
    
    syscall

    ret 0
#

sysenter "ios" ?

blissful galleon
#

so what do you see

waxen dune
#

using "ios"

blissful galleon
#

that is a compile time instruction telling the vm the program is using an ios module

waxen dune
#

what are these

blissful galleon
#

sysenter “ios” tells the runtime that we are about to call a function inside that module

#

and syscall calls that function with a specific fdx

waxen dune
pliant ingotBOT
#

@waxen dune has reached level 5. GG!

blissful galleon
#

of course it is not assembly you know

#

you can look at it like a different architecture

waxen dune
waxen dune
waxen dune
# blissful galleon cool!

your assembly language is pretty wild, i m lowkey into it but not gonna lie, Ive got serious doubts about how usable it is or if the syntax even makes sense thats why i m just asking questions for now

blissful galleon
#

so i am rewriting it

#

it was awful

#

it is pretty compared to what it was

waxen dune
#

nice

blissful galleon
blissful galleon
#
  • Optimisation
  • Procedures can now be declared within namespaces
  • Primitive classes
  • Fixes on the movasx instruction
manic flicker
#

That doesn't sound like asm

blissful galleon
blissful galleon
#

Bugfixes!

chilly bluff
#

Bro, try posting on Hacker News, the audience is bigger there and maybe there will be more positive recommendations.

blissful galleon
#

build 18 out after long time

#

big performance improvements

#

wiki reworked

blissful galleon
#

Build 27 out, compared to all versions before, this is the most stable and most efficient one yet

wet lodge
#

How are you so smart? I have no idea how to write on c++ your own assembler..

manic flicker
wet lodge
#

Not working yet, just began learning it, make cli project which asks for number, and asks what is the x² of the number, that's it

pliant ingotBOT
#

@wet lodge has reached level 1. GG!

storm zinc
#

wow

#

looks very juicy

blissful galleon
blissful galleon
#

we were all at one point just tinkering with std::cout and std::cin

storm zinc
blissful galleon
storm zinc
blissful galleon
#

абсолутели

storm zinc
#

ванхандрет персент

blissful galleon
#

персент

#

индид

storm zinc
#

сэнкью

blissful galleon
#

ћчжшђ

#

њљ

storm zinc
#

ай донт андерстанд зис щит

blissful galleon
#

хау донт ју андерстенд

storm zinc
#

бекас ай эм лэйзи матерфакэр

pliant ingotBOT
#

@storm zinc has reached level 5. GG!

blissful galleon
#

ви ар комјуникејтинг вери изли

storm zinc
#

индид

blissful galleon
#

вер ар ју фром

storm zinc
#

ай эм фром руссия

#

анд ю

blissful galleon
#

аи ем фром босниа

storm zinc
#

вов

#

саундз грэйт

blissful galleon
#

индид

#

слевик бродерс

storm zinc
#

агри

#

индид ви ар

#

а слевик бразерс

manic flicker
#

In English please

storm zinc
#

ор ай донт кноу жуст уз эй транслейтор

#

ай эм нот даубтинг тиз щит ю ноу?

manic flicker
storm zinc
blissful galleon
#

аххааахахахахаахаха

manic flicker
blissful galleon
#

he is speaking english

#

but in cyrillc

storm zinc
storm zinc
blissful galleon
#

ay agri

#

hahahha

storm zinc
#

yu knou zat?

blissful galleon
#

wat?

storm zinc
#

ciken but

#

ladno a vot eto po idee angliysckiy? @blissful galleon

blissful galleon
#

?

#

ay kent dikod dat

manic flicker
blissful galleon
#

We are terribly sorry for our behaviour!

blissful galleon
#

https://github.com/bracesoftware/newasm/releases/tag/build30

What's new or changed?

  • Added compile-time label name mangling with temporary namespaces. Read more in namespace docs!
  • The .text code section is now a synonym for .start, since the macros are now purely a compile-time thing.
  • Macros are now inlined at compile-time.
  • Around 5-10% performance improvements.
    Fixed issues
  • Fixed issue #30: compiler wasn't ever reporting any label redefinitions.
  • Fixed issue #31: compiler wasn't displaying correct code lines in error messages.
GitHub

NewASM Release Notes
Welcome to NewASM: an interpreted low-level programming language which combines explicit memory and register control, giving it a breeze of assembly-like feel, with high-level ...

blissful galleon
#

Build 31 is brewing with compile-time logic, better compiler optimizations and kernel/available host services updates

dim axle
#

Holyyy

blissful galleon
#

What's new or changed?

  • Anonymous functions have been severely improved regarding speed and functionality. Now you can use callc, retc, loop and such!
.text
    thread thisisfun -> {
        mov tlr, "this is really fun"
        call std::ios::writeln
        mov tlr, 908
        call std::ios::writeln
        mov tlr, 243.4
        call std::ios::writeln

        mov tlr, (proc)
            int 0x3
            mov rax, 4
            mov tlr, "Hi from lambda in thread\n"
            mov fdx, 1
            sysenter "ios"
            syscall
            {:lmao}
            syscall
            loop rax, lmao
            int 0x3
            halt 0
        (end)
    }

As you can see, lambdas in threads now have their own labels because the JIT compiler ignores the sealed labels within the (proc) block.

Another stupid example would be:

.text
    mov tlr, (proc)
        jmp label2
        {:label1}
        jmp label3
        {:label2}
        jmp label1
        {:label3}
        halt 0
    (end)
  • The NewASM compiler now allows following compile-time instructions for implementing very simple logic:
  1. ifdef: checks if a symbol/flag is defined;
  2. ifndef: checks if a symbol/flag is not defined;
  3. fi: used for ending an if block.
#

If you want to combine if-statements, just nest them, you don't need to use fi more than once.

def SMTH, 0
ifdef SMTH
    ifndef SMTH_ELSE
    ; do something
fi

There are no else variants, you have to end each if-block with fi.

  • Added a new concept of address fetching - a fetch instruction! This instruction is used to fetch a procedure or variable pointer, so we can use it with the this keyword. This is very important when optimizing your code because the compiler then can generate code that doesn't do any dictionary lookup.
.data
    ./data
        intg variable: 4
    ./!data
.text
    fetch data::variable ; get variable's address
    mov this, 6 ; give it a new value
    mov tlr, *this ; dereference the this ptr
    call std::ios::writeln ; prints 6

As you can see, we look for the variable only once, and then use the pointer, which means we get around 1.75x faster than using the variable's name twice.

We can also fetch addresses of procedures:

.text
    fetch std::ios::writeln
    mov tlr, "Hello"
    call this ; prints Hello
    
    mov tlr, 465
    call this
    ; .. etc
    ; this is way faster than letting the dispatcher
    ; look for the procedure every time you use call
    ; callc is still faster tho

If you don't want a variable to be fetched, use the new @safe attribute.

.data
    @safe
    intg var: 0
.text
    fetch var ; segmentation fault

Fixed issues

  • Fixed issue #32.
dim axle
#

Holy fuck this is wel amde

#

How long have you been working on this

blissful galleon
#

max 2 years

#

I started rewriting it just this year i think

#

So far i have made huge performance improvements

#

compilation and things got introduced just this year

#

literally everything has been rewritten in these few months because i started realising how bad the code was

dim axle
blissful galleon
blissful galleon
#

I am implementing a system in the virtual kernel/host service manager that is responsible for dedicating stack memory

Added a resb instruction that asks the kernel to give a specific thread n-bytes of heap space and use it as a thread-specific stack using push and pop instructions

My own language is terrorizing me to a point where I cannot distinguish c++ terminations from newasm crashes

blissful galleon
#

build 32 rc

What's new or changed?

  • Added the new resb instruction.
    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 internal 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.

Fixed issues

  • Fixed issue #36.
  • Fixed issue #38.
  • Fixed the loop instruction going into an infinite loop when the register is below 0 or 0.
waxen dune
#

looks like cisc

#

really hard work

#

well done man

blissful galleon
#

thanks !!

blissful galleon
#

build 32

#

What's new?

#
  • Added instructions for error handling, try and catch.
try
nop ; some code
catch ErrorLabel ; if there was an error, in code above, then jump to label
:ErrorLabel
; code that exits the app normally
; rax is gonna contain error code that was supposed to crash the application

Instruction try is used to begin a try-catch block. Essentially, try tells the program termination system that it should expect a catch instruction. When your app encounters an error, the program temporarily stops and checks if try was used, if it was it is going to jump to nearby catch instruction and then jump to an error-handling label.

.text
    try
        fetch nil ; set this ptr to nothing
        mov this, 0 ; forcefully invoke an error
        ; <- since the error happened, code stops here and jumps to catch
        nop ; more random code
    catch error ; we provide a label
    :come_back

    ; more code

    ret 0 ; terminate your program

    :error
    mov tlr, "Error handled, error code: "
    call std::ios::write
    mov tlr, *rax ; catch ins stores an error code in rax
    call std::ios::writeln
    jmp come_back

You can use these in threads, procedures and lambda procedures. It is important to note you cannot have these nested at singular identation level, however you can have a separate try-catch block within a lambda and a thread.

#

So, you can't do:

try
    try
        try
        catch what
    catch smth
catch no

If you call a procedure that contains an error within try-catch block, and that procedure doesn't have its own catch, the procedure forcefully terminates and fallbacks onto the parent try-catch block.

So, you can do:

.text
    proc ProcWithError
        pddsfdssd ; purposefully try to use a non-existing dyn lib
        mov tlr, "hi from ProcWithError"
        sysenter "ios"
        mov fdx, 1
        syscall
        halt 0
    end

    try
        call ProcWithError
    catch ErrorHandler

    
    try
        fetch nil
        mov this, 3
        nop
    catch ErrorHandler
:Continue    
    zero rax
    mov rax, 223 ; exit code
    ret *rax ; returns from the whole program to the host OS or newasm shell

:ErrorHandler
    mov tlr, "Error properly catched and handled, exit code: "
    call std::ios::write
    mov tlr, *rax
    call std::ios::writeln
    jmp Continue

Output will be:

Error properly catched and handled, exit code: 10

Or you can modify the ProcWithError procedure to just ignore the error with catch nil:

.text
    proc ProcWithError
        try
            pddsfdssd ; purposefully try to use a non-existing dyn lib
        catch nil ; just continue with execution
        
        mov tlr, "hi from ProcWithError\n"
        sysenter "ios"
        mov fdx, 1
        syscall
        halt 0
    end

And you get the output:

hi from ProcWithError
Error properly catched and handled, exit code: 14
#

Warnings

  1. Compiler is going to give you an error if you try to nest these on the same identation level.
  2. Compiler can optimize and remove empty try-catch blocks, such as:
try
catch smth
  1. You are going to get a runtime error if you do a callc within a try-catch block if the address you are jumping to has a try-catch block.
  • Optimized the following instructions:
  1. heap
  2. db
  3. free
dim axle
#

whoaaa

#

YOU HAVE COMPILER OPTIMIZATIONS?!

blissful galleon
#

yes

#

minimal like peephole or double code elimination etc

dim axle
#

handwritten?

dim axle
blissful galleon
#

wdym handwritten

dim axle
blissful galleon
# dim axle what's peephole

when it is removing or modifying a line the compiler is on, which means compiler's scope of view is just that line or two

#

bigger optimizations such as elimination of redundant functions etc require complete deepthrough analysis

#

of the whole program

blissful galleon
dim axle
blissful galleon
#

just hit 30k lines

#

i am planning few million

#

xd

dim axle
#

😭

#

you will definitely hit your goal

blissful galleon
#

amen

twilit estuary
#

Hi, uh, i am just new here and i dont knwo anything about C and Assembly. Please explain ts project (fyi i know C++)

blissful galleon
#

How can you know C++ and not know C

#

haha

blissful galleon
#

Managed to add some primitive code analysis in the optimizer so it checks for unreachable code blocks

#

So it just cuts them from the binary

#

Looks fancy

#

Love it tbh

#

Any more recommendations for different patterns that modern compilers do ?

twilit estuary
dim axle
#

raylib is a C library

twilit estuary
#

idk i just C++-ify Raylib

pliant ingotBOT
#

@twilit estuary has reached level 5. GG!

dim axle
twilit estuary
dim axle
#

and what do you make in CLI tools?

twilit estuary
dim axle
#

generator generating a generator generates build files to generate code

dim axle
twilit estuary
dim axle
#

how like uh how to use

twilit estuary
# dim axle how does it work?

well insetad of manually typing cmake -S . -B build -G Ninja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang in the terminal, you just type orbit build --ninja --use-compiler=clang. Preety neat and simple. Also uses Unity btw with --unity flag

#

I have yet to make an installer for this :/.

dim axle
#

like -DSOME_CUSTOM_VARIABLE=42

twilit estuary
dim axle
#

make your orbit project also use

#

orbit

#

bootstrap 💪 🚀

twilit estuary
#

hmm....

waxen dune
#
section bss      # initialize memory with zeros 
  entered reb 8  # 8 bytes 

section data     # data section 
  hello ascii "Hello, World!"  # hello message 
  password ascii "mypass"      # my password 
  match ascii "Unmatched!"     # error message 

section code                   # code section 
entry start                    # entry start 
start:            
  # read(0, entered, 6)
  mov 0, r0           
  mov entered, r1              
  mov 6, r2 
  syscall 0 

  # compare strings
  # compare_string(r1, r2)
  mov password, r1 
  mov entered, r2
  call compare_string
  
  # if r6 == 1 
  cmp r6, 1 
  je matchedfunction # then jump matchedfunction

  call unmatchedfunction # else call unmatchedfunction

compare_string: # args -> r1(string), r2(string) -> return value => r6
  load r1, r10  # r10 = *r1 
  load r2, r11  # r11 = *r2 

  cmp r10, 0    # if r10 == '\0'
  je .matched   # then jump .matched 

  cmp r11, 0    # if r11 == '\0'
  je .matched   # then jump .matched 

  cmp r10, r11  # if r10 == r11 -> if "m" == "m"
  je .matchednow  # then jump .matchednow

  jmp .unmatched  # else jump .unmatched

.matchednow:
  inc r1             # r1++ (r1 is pointer)
  inc r2             # r2++ (r2 is pointer)
  jmp compare_string # jump again compare_string (loop)

.matched:            # matched 
  mov 1, r6          # r6 => return value -> r6 = 1 (true)
  ret                # return to start 

.unmatched:          # unmatched
  mov 0, r6          # r6 => return value -> r6 = 0 (false)
  ret                # return to start

# r1 = 0 
# write(1, hello, 14)
matchedfunction:
  mov 0, r1
  mov 1, r0 
  mov hello, r1 
  mov 14, r2 
  syscall 1 
  jmp exit

# r1 = 0
# write(1, match, 10)
unmatchedfunction:
  mov 0, r1
  mov 1, r0 
  mov match, r1 
  mov 10, r2 
  syscall 1 

# exit(1)
exit: 
  mov 1, r0
  syscall 60
#

heres my own cpu arch code

#

its so simple and you can build literally everything on this

#

this is the instruction set:

mov, add, sub, mul, div, and, or, xor, nop, not, shl, shr, jmp, je, jne, jl, jg, cmp, call, ret, push, pop, hlt, inc, dec, load, store, entry.
#

and this things is VM layer instructions

import, syscall, print
#

print is debugger for registers

#

like: print r1
out:
DEBUG: 0

blissful galleon
#

very nice

#

what does entry instruction do

waxen dune
dim axle
#

ooo so it's customizable?!

waxen dune
#

the entry label is optional

waxen dune
dim axle
#

nvm i thought it couldn't be changed on linux apparemtly it can

waxen dune
#

i have lot of examples with this cpu assembly, i do a webserver (raw sockets) for linux

waxen dune
#
section data
    resp ascii "HTTP/1.1 200 OK" 13 10
         ascii "Content-Type: text/plain; charset=utf-8" 13 10
         ascii "Content-Length: 13" 13 10
         ascii "Connection: close" 13 10 13 10
         ascii "Hello, World!"
    # len 112

    sockaddr hword 2
             hword 8080 !
        # hword 36895      # BIG ENDIAN '8080'
            # the ! operator is swaps bytes like 901F to 1F90
            # or you can use bytes like this: 
            # byte 31 
            # byte 144
             word 0
             dword 0

section code
    # socket(AF_INET=2, SOCK_STREAM=1, IPPROTO_TCP=6)
    mov 2, r0
    mov 1, r1
    mov 6, r2
    syscall 41
    print r6
    mov r6, r8               # server_fd

    # bind(server_fd, &sockaddr, 16)
    mov r8, r0
    mov sockaddr, r1
    mov 16, r2
    syscall 49
    print r6

    # listen(server_fd, 16)
    mov r8, r0
    mov 16, r1
    syscall 50
    print r6

looper:
    # accept(server_fd, NULL, NULL)
    mov r8, r0
    mov 0, r1
    mov 0, r3
    syscall 43
    print r6
    mov r6, r9               # client_fd

    # write(client_fd, resp, 110)
    mov r9, r0
    mov resp, r1
    mov 112, r2              # len from comment above
    syscall 1
    print r6                 # bytes written

    # close(client_fd)
    mov r9, r0
    syscall 3
    print r6

    jmp looper

exit:
    mov 0, r0
    syscall 60
#

here

dim axle
#

wow

#

you made it entirely in assmebly

waxen dune
#

yeah

dim axle
#

very cool stuff

waxen dune
#

thanks

#

but new asm is really hard work, coolest one

blissful galleon
#

i really support this

#

i love seeing people make same stuff

#

my one is pretty disorganized when it comes actually mimicking real assembly

#

but yours is straight forward

#

thats another aspect i usually fail at

waxen dune
#

your one is actually a programming language

#

thats pretty cool