FASM

FASM (flat assembler) is a high-speed, single-pass assembler with a built-in macro language — effectively a low-level DSL for describing machine code directly. It assembles straight to binary, with no linker required for flat outputs.

Purpose

FASM turns human-readable assembly text into machine code in one pass and one step. Its macro language makes it programmable, so teams in OS development and the demoscene build their own code-generating idioms on top of it.

The Problem It Solves

Hand-written low-level code needs a toolchain that is fast, predictable, and free of hidden inputs. FASM is a single-pass assembler: it reads the source once, resolves labels on the fly, and emits the final binary — no intermediate object files and, for flat outputs, no linker. The macro engine then lets you treat assembly like a small programming language, generating repetitive instruction sequences from one definition.

Where It Fits

FASM targets the space below compilers: boot sectors, kernels, drivers, and demoscene intros where every byte is accounted for. It is the toolchain-side counterpart to the Forth philosophy on this phase’s other pages — minimal, transparent, and fully under the programmer’s control.

History

FASM is a famously small project with a famously dedicated following.

Origins

Tomasz Grysztar wrote and released the first version of FASM in 1999. The assembler is written in x86 assembly itself, so it is self-hosting, and the original binary was tiny — on the order of a hundred kilobytes. Its design goal was simplicity and speed: one pass, flat output, no dependencies.

Milestones

  • 1999–2000 — public release and FASM 1.x stabilization.
  • 2000s — adopted by the demoscene and by OS projects; the KolibriOS and MenuetOS kernels are written largely in FASM.
  • 2010s — portable versions for x86-64 and other targets; long-lived stable 1.7x series.
  • Today — the author’s experimental fasm g branch explores a new-generation assembler while 1.7x remains the production line.

Current Status

Mature and stable, with a deliberately slow release cadence: 1.7x has served production users for years. Development is mostly a one-person effort, but the code is open source under a BSD-style license and remains the standard choice in its niche.

Stage

FASM is finished software in the best sense: stable, documented, and unlikely to surprise you.

Maturity

Fully mature. The 1.7x series is battle-tested; the macro language and output formats (flat binary, MZ, PE, ELF, Mach-O) are stable and documented in the official manual.

Governance & Maintenance

Sole-maintainer project with a BSD-style license and an active forum community. Changes are conservative by design — compatibility matters more than new features.

Popularity & Usability

FASM does not appear in popularity indexes; its reputation lives in specific communities.

Adoption

Standard in demoscene and operating-system development circles. KolibriOS, a complete GUI operating system written in assembly, is its flagship user. Many bootloader and kernel tutorials use FASM because example binaries are easy to build and inspect.

Learning Curve

You need real x86/x64 knowledge first — FASM does not hide the machine. Its Intel-style syntax is close to NASM, so assembly skills transfer. The macro language is powerful but takes practice; that power is exactly what makes FASM a DSL for low-level code generation.

Tooling

A single executable, plus editor integrations and the flat assembler IDE (fasmw) on Windows. Flat output means no linker, no C runtime, and no build system for simple targets.

Use Cases

FASM is chosen when the artifact must be small, self-contained, and byte-exact.

Primary Domains

  • Boot sectors and bootloaders, where the output must be a raw flat binary.
  • Kernels and operating-system projects, including the FASM-written KolibriOS kernel.
  • Executables with hand-crafted PE/ELF headers when you want no toolchain surprises.
  • Demoscene intros, code golf, and reverse-engineering experiments.

Strengths

Speed (single pass), transparency (no hidden link step), byte-exact control, a tiny toolchain footprint, and macros that remove repetitive instruction patterns.

Weak Spots

Portability of handwritten code, minimal code reuse across architectures, and the productivity ceiling of assembly itself: FASM is deliberately not a compiler.

Performance

Two performance stories matter: how fast the assembler runs, and how good its output is.

Execution Model

Assembling is a single linear pass over the source, which is what makes FASM fast and keeps its memory footprint tiny. Output quality is entirely hand-controlled: you see every byte, so hot paths can be tuned to the instruction level.

Published Claims

Community reports consistently describe FASM as one of the fastest assemblers for its targets, and its output as some of the most compact on typical OS and kernel workloads — a direct consequence of single-pass design plus programmer control rather than a benchmarked guarantee.

Example

A complete Linux x86-64 program in FASM that writes a line and exits — no linker, no C library.

The Source File

; hello.asm — FASM flat assembler, ELF64 executable (Linux x86-64)
; Build: fasm hello.asm hello
; Run:   ./hello

format ELF64 executable 3          ; ELF 64-bit, executable; entry at _start
entry _start

segment readable executable
_start:
    mov     rax, 1                 ; rax = syscall 1 = write
    mov     rdi, 1                 ; rdi = file descriptor 1 = stdout
    mov     rsi, msg               ; rsi = address of the message
    mov     rdx, msg_len           ; rdx = message length in bytes
    syscall                        ; hand control to the kernel

    mov     rax, 60                ; rax = syscall 60 = exit
    xor     rdi, rdi               ; rdi = exit status 0
    syscall

segment readable writeable          ; .data — initialized memory
msg     db 'Hello from FASM!', 10  ; 10 is the newline byte
msg_len = $ - msg                  ; constant: length of msg

How to Build & Run

Download the single fasm executable from flatassembler.net, then:

fasm hello.asm hello   # one pass: source -> ELF binary
./hello                # prints "Hello from FASM!"

Note the line msg_len = $ - msg: $ is the current assembly position, so the constant is computed at assembly time — a taste of FASM’s compile-time computation.

Learn More

Official sources and free materials; the full categorized catalog is on the References & Downloads page.

Official Docs & Downloads

Community & Samples