> ## Documentation Index
> Fetch the complete documentation index at: https://hypotenuse.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Inline Assembly in C△: Writing asm Blocks with NASM

> Write inline asm blocks in C△ that compile to NASM-assembled object files and link seamlessly into your binary alongside ordinary C△ functions.

<Warning>
  **`asm` blocks and `asm` functions are not supported on Windows.** The MSVC build path does not wire up NASM, so any source file containing `asm` will fail to produce a working binary on Windows. See [Compiler Status](/reference/compiler-status) and the [Windows section](/installation#windows-support) of the installation guide.
</Warning>

C△ supports inline assembly through the `asm` keyword. There are two forms:

* **`asm` functions** — named, callable from C△ code with parameters and a return type. Must end with `return` unless the return type is `void`.
* **Anonymous `asm {}` blocks** — bare blocks embedded in surrounding code. Must end with an explicit exit (typically a `sys_exit` syscall), because control would otherwise fall through into the surrounding C△ code with the CPU still mid-assembly.

Each `asm` block is compiled to a separate `.asm` file, assembled with NASM, and linked into the final binary by GCC — fully transparent to the rest of your program. You write assembly with the same function-call interface as any other C△ function, using native C△ type declarations for parameters and `return` for the exit path.

## Basic Syntax

Define an `asm` function by opening a block with the `asm` keyword, a function name, a parameter list, and the `syntax` and `section` directives.

```c theme={null}
asm functionName(params) {
    syntax x86_64_linux
    section .text
    // assembly instructions
    return
}
```

Each element of the block has a specific role:

* **Function name** — becomes the global label in the generated `.asm` file and the callable symbol linked into your binary.
* **Parameters** — declared using C△ type syntax (e.g., `int a`). You do not use assembler directives like `%define` or `equ` for parameters.
* **`syntax`** — declares the target architecture and platform. Accepted values are `x86_64_linux`, `x86_64_elf`, and `arm64_macho`.
* **`section .text`** — mandatory for x86\_64 NASM targets. Use `.section __TEXT,__text` for `arm64_macho`.
* **`return;`** — emits a `ret` instruction. By itself, `return;` returns whatever value is currently in the platform return register (`rax` on x86\_64, `x0` on ARM64) — you do not need to declare a return type or write `return expr;` if your assembly has already placed the result there. Use `return expr;` when you want the compiler to move a C△-level expression into the return register for you before returning. **Required** for every non-`void` `asm` function; a `void` `asm` function may omit it (the compiler emits a bare `ret`).

<Note>
  Variable declarations inside `asm` blocks may omit semicolons — a newline terminates both declarations and instructions. This keeps the block readable alongside raw assembly mnemonics.
</Note>

## Example: Add Two Integers

The following `asm` function adds two integers and returns the result through the standard calling convention.

```c theme={null}
asm int addInts(int a, int b) {
    syntax x86_64_linux
    section .text
    int scratch = 0
    return a + b
}
```

Call it from the rest of your C△ program exactly as you would any ordinary function:

```c theme={null}
int result = addInts(3, 7);   // result = 10
```

The compiler generates a `.asm` file for `addInts`, assembles it with NASM, and links the resulting object file alongside the GCC-compiled C output.

## Example: Raw Syscall

When you need direct kernel access, write the instructions by hand. Use `mov` and `syscall` (or `svc` on ARM64) as you would in standalone assembly.

```c theme={null}
asm void exitProcess(int code) {
    syntax x86_64_elf
    section .text
    mov rax, 60    // sys_exit
    mov rdi, code
    syscall
}
```

`exitProcess` is declared `void` and terminates via `sys_exit`, so no `return` is needed. For any non-`void` `asm` function, `return` (or `return expr;`) is required.

## Anonymous `asm` Blocks

Anonymous `asm {}` blocks can appear at file scope or **nested inside any C△ scope** — most commonly the body of a function, but also `if`/`else`, loops, or any other block. Variables declared inside the block (using C△ declarations like `int counter = 0`) are **registered in the enclosing C△ scope**, so the surrounding C△ code can read and write them by name as if they had been declared there directly.

```c theme={null}
int main() {
    asm {
        syntax x86_64_linux
        section .data
        int counter = 0       // declared inside the asm block
        section .text
        mov [counter], 1
    }

    // `counter` is visible here because the enclosing scope is main()
    counter += 1;
    return counter;           // returns 2
}
```

<Warning>
  An anonymous `asm {}` block **must end with an explicit exit** when it is the final thing the program runs — otherwise control falls through into the surrounding C△ code with the CPU still mid-assembly. Use the platform's exit syscall — `mov rax, 60; mov rdi, 0; syscall` on x86\_64 Linux or `mov x16, 1; mov x0, #0; svc #0x80` on ARM64 macOS. When the block is embedded mid-scope (as above) and the surrounding C△ code is expected to keep running, end with a `ret`-free fallthrough is acceptable — just make sure the CPU state on exit is consistent with the surrounding C△ code's expectations. Unlike `asm` functions, `return` is **not** valid here — anonymous blocks do not have a return frame.
</Warning>

For embedding raw assembly without defining a named function, use a bare `asm {}` block. The earlier example above shows a nested block; the example below shows a top-level block that exits the process directly.

```c theme={null}
// x86_64 Linux — exit the process with status 0
asm {
    syntax x86_64_linux
    section .data
    int counter = 0
    section .text
    mov rax, 60      // sys_exit
    mov rdi, 0       // exit status
    syscall
}
```

Use anonymous blocks when you need to set up data labels, share locals with the surrounding C△ scope, or emit architecture-specific instructions that are not naturally expressed as a function call.

## Syntax Targets

The `syntax`directive tells the compiler which architecture and platform to target when generating the `.asm` file and choosing the NASM output format.

| Syntax Target  | Architecture | Platform | Text Section Directive   |
| -------------- | ------------ | -------- | ------------------------ |
| `x86_64_linux` | x86\_64      | Linux    | `section .text`          |
| `arm64_macho`  | ARM64        | macOS    | `.section __TEXT,__text` |

## Compilation Pipeline

The Hypotenuse Compiler processes `asm` blocks on a separate path from ordinary C△ code. Both paths converge at the GCC linker step to produce the final binary.

```text theme={null}
.ctri source
  └─▶ code gen ─▶ .c file ─▶ GCC ──────────────────────┐
  └─▶ asm blocks ─▶ .asm files ─▶ NASM ─▶ GCC linker ─▶ binary
```

You do not need to invoke NASM or manage object files yourself. Pass your `.ctri` source to `hypc` and the entire pipeline runs automatically.

## Rules

<Note>
  Each `asm` block is entirely opaque to the simulation pass. The compiler does not perform last-use analysis or `autoremove` tracking inside `asm` bodies. Manage any heap pointers you pass into assembly code manually, or perform a Robbery before the pointer enters the block.
</Note>

<Note>
  Variables declared inside `asm` functions are registered both for import access from other modules and within the function's own scope. Variables declared in bare `asm {}` blocks are registered in the **enclosing C△ scope** — whether that's a function body, a control-flow block, or file scope — and can be referenced by name from the surrounding C△ code as if they had been declared there directly.
</Note>

<Warning>
  Do not use raw assembler data directives such as `db`, `dw`, or `dd` inside `asm` blocks. Represent data storage with C△ variable declarations instead. The compiler translates these into the correct NASM output for your target.
</Warning>

<Warning>
  The text section directive is mandatory in every `asm` block. Omitting it causes a NASM assembly error at build time. Use `section .text` for x86\_64 targets and `.section __TEXT,__text` for `arm64_macho`.
</Warning>

* Use `return;` to emit `ret` — it returns whatever is in the platform return register (`rax` / `x0`), so a typed return annotation is optional when your assembly already populates it. Use `return expr;` to move a C△-level expression into the return register first. Do not write `ret` directly.
* Each `asm` block produces its own `.asm` file. Name your `asm` functions clearly — the function name becomes the exported symbol linked into the final binary.
