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

# Assembler functions

export const Aside = ({type = "note", title = "", icon = "", iconType = "regular", children}) => {
  const asideVariants = ["note", "tip", "caution", "danger"];
  const asideComponents = {
    note: {
      outerStyle: "border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10",
      innerStyle: "text-sky-900 dark:text-sky-200",
      calloutType: "note",
      icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-sky-500" aria-label="Note">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
    },
    tip: {
      outerStyle: "border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10",
      innerStyle: "text-emerald-900 dark:text-emerald-200",
      calloutType: "tip",
      icon: <svg width="11" height="14" viewBox="0 0 11 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto" aria-label="Tip">
          <path d="M3.12794 12.4232C3.12794 12.5954 3.1776 12.7634 3.27244 12.907L3.74114 13.6095C3.88471 13.8248 4.21067 14 4.46964 14H6.15606C6.41415 14 6.74017 13.825 6.88373 13.6095L7.3508 12.9073C7.43114 12.7859 7.49705 12.569 7.49705 12.4232L7.50055 11.3513H3.12521L3.12794 12.4232ZM5.31288 0C2.52414 0.00875889 0.5 2.26889 0.5 4.78826C0.5 6.00188 0.949566 7.10829 1.69119 7.95492C2.14321 8.47011 2.84901 9.54727 3.11919 10.4557C3.12005 10.4625 3.12175 10.4698 3.12261 10.4771H7.50342C7.50427 10.4698 7.50598 10.463 7.50684 10.4557C7.77688 9.54727 8.48281 8.47011 8.93484 7.95492C9.67728 7.13181 10.1258 6.02703 10.1258 4.78826C10.1258 2.15486 7.9709 0.000106649 5.31288 0ZM7.94902 7.11267C7.52078 7.60079 6.99082 8.37878 6.6077 9.18794H4.02051C3.63739 8.37878 3.10743 7.60079 2.67947 7.11294C2.11997 6.47551 1.8126 5.63599 1.8126 4.78826C1.8126 3.09829 3.12794 1.31944 5.28827 1.3126C7.2435 1.3126 8.81315 2.88226 8.81315 4.78826C8.81315 5.63599 8.50688 6.47551 7.94902 7.11267ZM4.87534 2.18767C3.66939 2.18767 2.68767 3.16939 2.68767 4.37534C2.68767 4.61719 2.88336 4.81288 3.12521 4.81288C3.36705 4.81288 3.56274 4.61599 3.56274 4.37534C3.56274 3.6515 4.1515 3.06274 4.87534 3.06274C5.11719 3.06274 5.31288 2.86727 5.31288 2.62548C5.31288 2.38369 5.11599 2.18767 4.87534 2.18767Z"></path>
        </svg>
    },
    caution: {
      outerStyle: "border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10",
      innerStyle: "text-amber-900 dark:text-amber-200",
      calloutType: "warning",
      icon: <svg className="flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-label="Warning">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
        </svg>
    },
    danger: {
      outerStyle: "border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10",
      innerStyle: "text-red-900 dark:text-red-200",
      calloutType: "danger",
      icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" className="text-red-600 dark:text-red-400/80 w-4 h-4" aria-label="Danger">
          <path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12l176.6 0c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM256 128c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"></path>
        </svg>
    }
  };
  let variant = type;
  let gotInvalidVariant = false;
  if (!asideVariants.includes(type)) {
    gotInvalidVariant = true;
    variant = "danger";
  }
  const iconVariants = ["regular", "solid", "light", "thin", "sharp-solid", "duotone", "brands"];
  if (!iconVariants.includes(iconType)) {
    iconType = "regular";
  }
  return <>
      <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`} data-callout-type={asideComponents[variant].calloutType}>
        <div className="mt-0.5 w-4" data-component-part="callout-icon">
          {}
          {icon === "" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}
        </div>
        <div className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`} data-component-part="callout-content">
          {gotInvalidVariant ? <p>
              <span className="font-bold">
                Invalid <code>type</code> passed!
              </span>
              <br />
              <span className="font-bold">Received: </span>
              {type}
              <br />
              <span className="font-bold">Expected one of: </span>
              {asideVariants.join(", ")}
            </p> : <>
              {title && <p className="font-bold">{title}</p>}
              {children}
            </>}
        </div>
      </div>
    </>;
};

Functions in Tolk may be defined using assembler code.
It's a low-level feature that requires deep understanding of stack layout, [Fift](/languages/fift/overview), and [TVM](/tvm/overview).

## Standard functions are actually `asm` wrappers

Many functions from [stdlib](/languages/tolk/features/standard-library) are translated to Fift assembler directly.

For example, TVM has a `HASHCU` instruction: "calculate hash of a cell".
It pops a cell from the stack and pushes an integer in the range 0 to 2^256-1.
Therefore, the method `cell.hash` is defined this way:

```tolk theme={null}
@pure
fun cell.hash(self): uint256
    asm "HASHCU"
```

The type system guarantees that when this method is invoked, a TVM `CELL` will be the topmost element (`self`).

## Custom functions are declared in the same way

```tolk theme={null}
@pure
fun incThenNegate(v: int): int
    asm "INC" "NEGATE"
```

A call `incThenNegate(10)` will be translated into those commands.

A good practice is to specify `@pure` if the body does not modify TVM state or throw exceptions.

The return type for `asm` functions is mandatory (for regular functions, it's auto-inferred from `return` statements).

<Aside type="note">
  The list of assembler commands can be found here: [TVM instructions](/tvm/instructions).
</Aside>

## Multi-line asm

To embed a multi-line command, use triple quotes:

```tolk theme={null}
fun hashStateInit(code: cell, data: cell): uint256 asm """
    DUP2
    HASHCU
    ...
    ONE HASHEXT_SHA256
"""
```

It is treated as a single string and inserted as-is into Fift output.
In particular, it may contain `//` comments inside (valid comments for Fift).

## Stack order for multiple slots

When calling a function, arguments are pushed in a declared order.
The last parameter becomes the topmost stack element.

If an instruction results in several slots, the resulting type should be a tensor or a struct.

For example, write a function `abs2` that calculates `abs()` for two values at once: `abs2(-5, -10)` = `(5, 10)`.
Stack layout (the right is the top) is written in comments.

```tolk theme={null}
fun abs2(v1: int, v2: int): (int, int)
    asm             // v1 v2
        "ABS"       // v1 v2_abs
        "SWAP"      // v2_abs v1
        "ABS"       // v2_abs v1_abs
        "SWAP"      // v1_abs v2_abs
```

## Rearranging arguments on the stack

Sometimes a function accepts parameters in an order different from what a TVM instruction expects.
For example, `GETSTORAGEFEE` expects the order "cells bits seconds workchain".
But for more clear API, workchain should be passed first.
Stack positions can be reordered via the `asm(...)` syntax:

```tolk theme={null}
fun calculateStorageFee(workchain: int8, seconds: int, bits: int, cells: int): coins
    asm(cells bits seconds workchain) "GETSTORAGEFEE"
```

Similarly for return values. If multiple slots are returned, and they must be reordered to match typing,
use `asm(-> ...)` syntax:

```tolk theme={null}
fun asmLoadCoins(s: slice): (slice, int)
    asm(-> 1 0) "LDVARUINT16"
```

Both the input and output sides may be combined: `asm(... -> ...)`.
Reordering is mostly used with `mutate` variables.

## `mutate` and `self` in assembler functions

The `mutate` keyword (see [mutability](/languages/tolk/syntax/mutability)) works
by implicitly returning new values via the stack — both for regular and `asm` functions.

For better understanding, let's look at regular functions first.
The compiler does all transformations automatically:

```tolk theme={null}
// transformed to: "returns (int, void)"
fun increment(mutate x: int): void {
    x += 1;
    // a hidden "return x" is inserted
}

fun demo() {
    // transformed to: (newX, _) = increment(x); x = newX
    increment(mutate x);
}
```

How to implement `increment()` via asm?

```tolk theme={null}
fun increment(mutate x: int): void
    asm "INC"
```

The function still returns `void` (from the type system's perspective it does not return a value),
but `INC` leaves a number on the stack — that's a hidden "return x" from a manual variant.

Similarly, it works for `mutate self`.
An `asm` function should place `newSelf` onto the stack before the actual result:

```tolk theme={null}
// "TPUSH" pops (tuple) and pushes (newTuple);
// so, newSelf = newTuple, and return `void` (syn. "unit")
fun tuple.push<X>(mutate self, value: X): void
    asm "TPUSH"

// "LDU" pops (slice) and pushes (int, newSlice);
// with `asm(-> 1 0)`, we make it (newSlice, int);
// so, newSelf = newSlice, and return `int`
fun slice.loadMessageFlags(mutate self): int
    asm(-> 1 0) "4 LDU"
```

To return `self` for chaining, just specify a return type:

```tolk theme={null}
// "STU" pops (int, builder) and pushes (newBuilder);
// with `asm(op self)`, we put arguments to correct order;
// so, newSelf = newBuilder, and return `void`;
// but to make it chainable, `self` instead of `void`
fun builder.storeMessageOp(mutate self, op: int): self
    asm(op self) "32 STU"
```

## `asm` is compatible with structures

Methods for structures may also be declared as assembler ones knowing the layout: fields are placed sequentially.
For instance, a struct with one field is identical to this field.

```tolk theme={null}
struct MyCell {
    private c: cell
}

@pure
fun MyCell.hash(self): uint256
    asm "HASHCU"
```

Similarly, a structure may be used instead of tensors for returns.
This is widely practiced in `map<K, V>` methods over TVM dictionaries:

```tolk theme={null}
struct MapLookupResult<TValue> {
    private readonly rawSlice: slice?
    isFound: bool
}

@pure
fun map<K, V>.get(self, key: K): MapLookupResult<V>
    builtin
// it produces `DICTGET` and similar, which push
// (slice -1) or (null 0) — the shape of MapLookupResult
```

## Generics in `asm` should be single-slot

Take `tuple.push` as an example. The `TPUSH` instruction pops `(tuple, someVal)` and pushes `(newTuple)`.
It should work with any `T`: int, int8, slice, etc.

```tolk theme={null}
fun tuple.push<T>(mutate self, value: T): void
    asm "TPUSH"
```

A reasonable question: how should `t.push(somePoint)` work?
The stack would be misaligned, because `Point { x, y }` is not a single slot.
The answer: this would not compile.

```ansi theme={null}
dev.tolk:6:5: error: can not call `tuple.push<T>` with T=Point, because it occupies 2 stack slots in TVM, not 1

    // in function `main`
   6 |     t.push(somePoint);
     |     ^^^^^^
```

Only regular and built-in generics may be instantiated with variadic type arguments, `asm` cannot.

## Do not use `asm` for micro-optimizations

Introduce assembler functions only for rarely-used TVM instructions that are not covered by stdlib.
For example, when manually parsing merkle proofs or calculating extended hashes.

However, attempting to micro-optimize with `asm` instead of writing straightforward code is not desired.
The compiler is smart enough to generate optimal bytecode from consistent logic.
For instance, it automatically inlines simple functions, so create one-liner methods without any worries about gas:

```tolk theme={null}
fun builder.storeFlags(mutate self, flags: int): self {
    return self.storeUint(32, flags);
}
```

The function above is better than "manually optimized" as `32 STU`. Because:

* it is inlined automatically
* for constant `flags`, it's merged with subsequent stores into `STSLICECONST`

See [compiler optimizations](/languages/tolk/features/compiler-optimizations).
