| | {{infobox |
| | | title = ALB FASM backend |
| | | target_flag = `-t fasm` |
| | | produces = x86-64 Flat Assembler source (.asm) |
| | | output = Windows PE64 — console, GUI, or DLL |
| | | assembler = [Flat Assembler](https://flatassembler.net) (fasm.exe) |
| | | emitter_unit = `Emit_Native_FASM` (emit_native_fasm.adb) |
| | | status = Primary native backend; `--build` supported |
| | }} |
| | |
| | The **ALB FASM backend** is [[AdaLogic BASIC]]'s flagship native emitter: it turns an ALB program into **x86-64 assembly source** for the [Flat Assembler](https://flatassembler.net), which then assembles — in a single pass, in milliseconds — into a real Windows PE64 executable with no linker and no C runtime requirement beyond what ALB brings itself. |
| | |
| | ```alb One-liner |
| | albt hello.alb -t fasm --build |
| | → fasm_hello/hello.asm → fasm.exe → hello.exe (a few kilobytes, instantly) |
| | ``` |
| | |
| | It is one of only three backends — with [[ALB C backend|C]] and [[ALB FASM16 backend|FASM16]] — where `--build` is supported end to end: the compiler emits the file **and** drives the assembler. |
| | |
| | ## What it produces |
| | |
| | Every generated file opens the same way — a comment banner, then the PE64 header: |
| | |
| | ```text |
| | ; ========================================================== |
| | ; GENERATED BY ADALOGIC BASIC (ALB) TRANSPILER |
| | ; TARGET: x64 FASM (Bare-Metal PE Executable) |
| | ; ========================================================== |
| | format PE64 Console |
| | stack 1000000h |
| | heap 1000000h |
| | entry start |
| | include 'win64a.inc' |
| | ``` |
| | |
| | The emitter supports three output formats, switched by flags such as `--dll`: |
| | |
| | | Format | Emitted header | Result | |
| | | --- | --- | --- | |
| | | Console | `format PE64 Console` | Command-line .exe — the default | |
| | | GUI | `format PE64 GUI` | Windowed .exe — no console | |
| | | DLL | `format PE64 DLL at 10000000h` | Shared library with an ALB export entry | |
| | |
| | Console and GUI builds reserve a **16 MiB stack and 16 MiB heap** (`stack 1000000h / heap 1000000h`) — generous headroom for recursion and the temporal-state system, at zero runtime cost since Windows commits the pages lazily. |
| | |
| | ## The file anatomy |
| | |
| | A FASM output is organized into the classic PE sections: |
| | |
| | - **`.text`** — code: the runtime library, then your program under `start:` |
| | - **`.data`** — initialized writable data: string literals, buffers, the GC grid |
| | - **`.bss`** — zero-initialized storage |
| | - **`.idata`** — imports: only the Win32 functions actually used (printf, ExitProcess, GDI, winsock…) |
| | - **`.reloc`** — relocations, emitted for DLL builds |
| | |
| | ## The macro layer — FASM as co-optimizer |
| | |
| | Here is the part that surprises people. The emitter writes expressions in a deliberately simple infix-looking style — `mov rax, a + mov rax, b` — and then defines an `ALB_LET` macro that uses FASM's `match` directive to **rewrite those patterns into optimized code at assembly time**: |
| | |
| | ```text |
| | match =0 =mov =rax, dest, =mov =rax, a + =mov =rax, b, matched line { |
| | mov rax, a |
| | add rax, b |
| | mov dest, rax |
| | define matched 1 |
| | } |
| | ``` |
| | |
| | The assembler itself pattern-matches each emitted statement and fuses the verbose three-instruction form into a tight `mov/add/mov`. The compiler stays simple; the assembler does the peephole optimization. Two tools, each doing what it's best at. |
| | |
| | Alongside it, `ALB_MASK_OP` provides **branchless selection** — a conditional computed as a bitmask (`neg / and / not / and / or`) instead of a jump, for the constant-time code paths where a branch would be unpredictable or unsafe. |
| | |
| | ## The hardened runtime |
| | |
| | ALB does not trust the machine blindly — the emitted program carries a safety runtime: |
| | |
| | ```text |
| | ALB_Runtime_Trap_DivZero: |
| | sub rsp, 40 |
| | invoke printf, ALB_Runtime_DivZero |
| | invoke ExitProcess, 1 |
| | ``` |
| | |
| | Divide by zero, index out of bounds, or leave a declared range and the program *reports and halts* rather than corrupting onward — the Ada philosophy showing through the BASIC surface. Every runtime routine is wrapped in FASM's `if used … end if`, so **the assembler strips everything your program never calls**: a hello world links in almost none of the library below. |
| | |
| | And the library is large: |
| | |
| | - **Strings** — `ALB_Str_Eq`, `Mid/Left/Right`, `ALB_Hash`, length/copy/concat with fixed-capacity vaults |
| | - **Console** — prompts, buffered input with a hand-rolled S64 parser (`ALB_Input_Try_Parse_S64`, whitespace and sign handled in raw asm) |
| | - **Files** — open/read/write/close/len/seek, plus `ALB_OS_Load`/`ALB_OS_Flush` whole-file vaults |
| | - **Logic** — a real Prolog-style knowledge base: `ALB_Assert`, `ALB_Query`, `ALB_Find`, `ALB_Retract` — the **Prolog** half of ALB's ancestry, implemented in machine code |
| | - **Math** — sqrt/sine/cosine/abs, random, and the **PURE** engine (`ALB_Pure_Add/Sub/Mul/Div/Pow`) — exact rational arithmetic with numerator and denominator kept separate, so ⅓ + ⅓ stays exactly ⅓ |
| | - **Graphics & sound** — Win32 window creation, message loop, put-pixel, BGR colors, key and mouse state, music buffer streaming |
| | - **Data formats** — a complete **FITS** astronomy file reader (card loop, BITPIX parsing, NAXIS) and an **INI** parser — emitted only if used |
| | - **FFI** — `ALB_Load_Foreign_Symbol` loads DLL functions at runtime; ALB's `IMPORT_DLL` lowers to direct calls |
| | |
| | ```fact The odd superpowers |
| | The same emitter file also implements **temporal variables** (a ring-buffer history so a variable can be read in the past), **reversible blocks** (add/sub/xor/rol/ror/swap/not/neg that can run backwards), `CLAIM/DROP/BIND/SWEEP` memory ownership, and **native ASM blocks** — raw assembly embedded inside ALB source for when only a specific instruction will do. |
| | ``` |
| | |
| + | ## The learning runtime — forged by the compiler |
| + | |
| + | `MARKOV MODEL`, `PREDICT MARKOV`, `NEURAL TOPOLOGY`, `INFER NETWORK`, and `TRAIN NETWORK` aren't library calls — they're **language-level statements** with their own AST node kinds. When `albt` sees one, it registers the model in compile-time tables (up to **128 Markov models** and 32,768 transition weights; up to **64 neural topologies** sharing 512 layer slots), bakes the declared matrices straight into `.data`, and flips a `Runtime_Used` flag. Then the compiler's own **Phase 4.5 — "Forging FASM Extended Runtime"** — appends only the runtimes that were actually requested: |
| + | |
| + | - **`ALB_Markov_Predict:`** — a ~30-instruction argmax: index the transition-matrix row for the current state, walk it once, return the likeliest next state |
| + | - **`ALB_NN_Apply_Activation:`** — activation by code: linear, ReLU, step, and a clamped ±128→×8 scaled tanh — all integers |
| + | - **`ALB_NN_Infer:`** — a pure-integer forward pass over a meta-descriptor of layer sizes, offsets, weights, and biases |
| + | - **`ALB_NN_Train:`** — a perceptron-style delta rule (`delta ∈ {-1, 0, +1}`: nudge the bias, nudge each weight where the input fired) refining the output layer per epoch |
| + | |
| + | And the weights themselves are *seeded by the compiler*: `Seed_Neural_Weight` in `albt` assigns deterministic structured guesses — identity patterns for same-size layers (weight 256 = 1.0 at ¹⁄₂₅₆ scale), +256/−256 split-pairs when a layer halves, wrap-around when it grows. No RNG; the same program always starts from the same brain. |
| + | |
| + | ```warn FASM-only: EMOTION |
| + | One learning feature is exclusive to this backend: `EMOTION` — declared emotional-state axes (max 8) baked as `ALB_EMOTION_<name>` byte tables — and `PREDICT MARKOV … WITH EMOTION`, a Markov predictor driven by an emotion vector. The compiler itself enforces it: *"EMOTION requires -t fasm (not available on FASM16/other backends)."* |
| + | ``` |
| + | |
| | ## Concurrency, honestly stated |
| | |
| | `SPAWN` on this backend is documented in the emitter's own words as *"synchronous on FASM (same-core call)"* — and `SYNC`/`ATOMIC` lower to `mfence`. The honesty matters: the multi-core dispatch is real on the [[ALB C backend]], deliberately sequential here. |
| | |
| | ## The blackbox |
| | |
| | `--embed-blackbox` installs a **VEH crash reporter** — a vectored exception handler and a heap-free append-only dump path (`ALB_BB_Append_Z`, `ALB_Blackbox_Handler`) that writes a forensic record when a native fault would otherwise vanish silently. A flight recorder for the generated executable, compiled in only when asked for. |
| | |
| | ## Under the hood — the emitter itself |
| | |
| | The backend is the Ada package `Emit_Native_FASM` (~7,300 lines, SPARK-annotated). Its design is a small lesson in compiler construction: |
| | |
| | - **Two text buffers** — `Buffer_Global` (lands in `.data`/`.bss`) and `Buffer_Main` (lands in `.text`) — so declarations and code accumulate independently and merge at flush time |
| | - **A stable Emit_* API** — `Emit_If_Start`, `Emit_For_Start`, `Emit_BinOp`… The same call surface every backend implements, which is how one front end drives ~23 targets |
| | - **Expression scrubbing** — before emitting an operator the emitter backspaces trailing newlines so infix text lands on one line, which is what makes the `ALB_LET` match-macro possible |
| | |
| | ```note Where it lives |
| | In the source tree: `EMITTER/emit_native_fasm.adb`, driven by `albt.adb`. Emitted sources land in `fasm_<name>/` by default. The whole toolchain is Apache 2.0. |
| | ``` |
| | |
| | ## See also |
| | |
| | - [[AdaLogic BASIC]] — the language this emits |
| | - [[ALB FASM16 backend]] — its 16-bit sibling |
| | - [[ALB C backend]] — the portable sibling |
| | - [[History of Programming]] — where assemblers fit in the long arc |
| | - [[Konrad Zuse]] · [[Z3]] · [[Plankalkül]] — the other end of that arc |
| | |
| | [[Category:Backends]] |
| | [[Category:AdaLogic BASIC]] |
| | |