💾 Archived View for stack.tilde.cafe › gemlog › 2022-09-11.assembly.gmi captured on 2024-08-18 at 17:52:40. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-09-08)
-=-=-=-=-=-=-
I've been itching to code in assembly for a few weeks now. It's just a part of my cycle - getting tired of the complexity and bulk of high-level languages and wanting to do something direct and simple - and what is more direct than coding assembly-language instructions on a CPU?
Playing around with KolibriOS just exacerbated the itch. An OS coded entirely (well, almost, as recently C and even Oberon are used) in assembly! Of course it's too good to be true - mistakes were made.
The biggest issue with KolibriOS is that the founding fathers were obviously living in Windows. There is no command line - except as an afterthought, and no one uses it. That has dire consequences:
I attempted coding from inside the OS running in qemu (surprisingly stable!). The assembler pops up a dialog box asking for a filename and a path. Every time I start it it defaults to some dumb example, and I have to click and change both. Every time. There is no configuration file, invoking from the shell just ignores parameters.
So it's largely a joke. But a fun and surprisingly stable joke. But the debugger is surprisingly workable, and I managed to get comfy with an editor. So yes, you can actually assemble some stuff and run it. But in a painful way.
Before I was tired of this command-line-less environment, I coded up half a Forth, just out of habit.
It's been a while since I've been in 32-bit land, and this time around it does not feel claustrophobic! There are just enough registers, and the assembly for a Forth kernel just poured out of my brain into the weird editor.
Forth stores each word (subroutine) separately along with its name, in ASCII. During compilation, names are looked up and appropriate code generated.
But names are a pain in the butt -- they are variable length, and we need to keep a length byte around. Parsing text and comparing it against the names in the dictionary is painful and slow.
In my last few research Forth-like languages I gave up on name storage, and store a hash of the name instead. When parsing I hash the name for lookup, and lookup is trivial. Hashes are fixed-size, so much easier to store. A 32-bit FN1a hash is very, very unlikely to collide, so no problem there.
And boom, a day later a Forth plops out - not yet self-contained, but running tokenized code. I need to get the compiler up still, but the inner interpreter is running like a charm.
The itch is being scratched several different ways.