16 comments

[ 4.3 ms ] story [ 48.8 ms ] thread
Not bad. It reminds me of MASM. It's rather surprising high-level assemblers are so rare now.
Why is it suprising? There is no real need for people writing hand tuned assembly any more. And great optimized assembly code can work like crap on next gen of chip. Why bother?
demoscene is timeless
Most of the demoscene fun nowadays is fragment shader competitions.
At what level should one code to be confident the backend will do proper chip-specific optimization? RTL? Or is that already too low level?
In the GNU toolchain world that sees a lot of embedded use nowadays, it's pretty common for the preprocessor to be used for assembly files. A file named with a capital .S suffix is preprocessed.

You might think that the preprocessor is "weak", which it is, but, look, I used it to define a loop language for Awk, with not only a variety of standard clauses but an easy way to write new clauses.

You can loop over strings, associative arrays, ranges, find maxima, minima, argmax, count, collect lists (there is a Lisp-like layer defining cons cells) and such.

https://www.kylheku.com/cgit/cppawk/about/

(See the info about <iter.h>. There is a man page covering the loop macro and the test suite has coverage of all its clauses in testcases-iter).

woah this is cool, thanks!
They were never a thing in the UNIX world, which is where most stuff nowadays comes from.

Such Macro-Assemblers are also quite common on the mainframe world, besides the 16 bit home micros.

In any case, nasm and yasm do exist as FOSS version of such ideas.

I don't see how the example works, it has two separate routines, neither of which does any syscalls, windows calls, interrupts, nor I/O of any kind.

[also] The makefile calls on src/printf.hpp, which is missing.

(comment deleted)
It appears that the language uses "return" as a synonym for the SYSCALL x86_64 instruction: https://github.com/wellang/well/blob/main/src/syscall_interp...

The example code is equivalent to:

    write(1, "hello world!", 12);
    exit(0);
It's basically just doing some very simple string substitution on the input, and then piping the result to the nasm assembler.
Probably just because of the title of the post, this made me think of Terse (terse.com).

Wow, I wonder if Jim Neil really is still selling it (it looks like he is). I wonder if it still comes on an 1.44MB diskette (http://terse.com/neildeal.htm#whatget) :-D

I never used it, nor saw it in use by anyone else. I just remember coming across it multiple times when looking at PC assembly language books and tools.

Maybe an IR language would be some kind of less worse compromise for portability and to avoid complex syntax (C is already too rich and flexible). For instance like QBE (http://c9x.me/compile). There is llvm, but its grotesque and absurd c++ complexity does exclude it, de-facto.

The main pitfall with IR (like QBE), is intrinsics, because QBE does a bit of optimization and writting "hardware accelerated" intrinsics in a portable way forces the IR to generalize some instruction properties which "could" make even its simple optimization passes a nightmare.

That said, I would go RISC-V assembly (64bits) with a conservative usage of a pre-processor.

You might find something interesting if you were to look at virtual-machines - many are used for implementing scripting-languages, so while you'd not be writing assembly-code, you'd be writing "bytecode" programs.

You could write bytecode for Lua, or bytecode for Python for example.

I had a fun few weeks writing a simple virtual-machine, and a "compiler" which turns a simple assembly-language-like input into bytecodes which are then interpreted:

https://github.com/skx/go.vm/

Other examples, along with lua/python which were already mentioned, might include "Writing a compiler in go" this turns a scripting-language into a set of opcodes which a VM executes:

* https://compilerbook.com/

I made a programming language when I was younger... on a Commodore+4, believe it or not. The gist of it was that it was basically a 6502 macro assembler, but had pseudo-ops for 16 bit math & logic operations, and basic control structures (if/then, do/loop/exit, etc.).

It also had a structured way to define variables and new opcodes (subroutines). It actually seemed to be a productive language that allowed you to transition from low-level to high-level programming pretty well. It didn't insulate you from needing to know details of the CPU, but that's really necessary for any sort of performant computing.

I stopped working on it when I released I was basically reinventing Forth.