R_ASM(3)

NAME
r_asm - Assembler and disassembler library for radare2

SYNOPSIS
#include <r_asm.h>

DESCRIPTION
The r_asm API exposes radare2's high level assembler and disassembler primitives and the glue between them.

It is implemented as a frontend for the r_arch api that provides the architecture logic to encode and decode instructions. But offers support for multiline assembler with directive handling and pseudo disassembling and parsing plugins. Routines operate on the RAsm context which holds architecture configuration, current program counter and parser state. Results for multi-instruction operations are returned in RAsmCode objects which contain raw bytes, the disassembly text and per-assembly metadata.

INITIALIZATION
Before assembling or disassembling you must create and configure an RAsm r2 RAsm r_asm_set_user_ptr(()) RCore

    /* Initialization API (prototypes) */
    RParse *r_parse_new (void);
    void r_parse_free (RParse *p);
    RAsm *r_asm_new (void);
    void r_asm_free (RAsm *a);
    void r_asm_set_user_ptr (RAsm *a, void *user);
    bool r_asm_use (RAsm *a, const char *name);
    int r_asm_set_bits (RAsm *a, int bits);
    int r_asm_set_pc (RAsm *a, ut64 pc);

Example initialization and cleanup:

    RAsm *a = r_asm_new();
    /* choose architecture and word size */
    r_asm_use (a, "x86");
    r_asm_set_bits (a, 64);
    /* set current location for relative operands and disassembly helpers */
    r_asm_set_pc (a, 0x1000);
    /* when embedding in r2: r_asm_set_user_ptr (a, core); */
    r_asm_free (a);

ASSEMBLY
The assembler API provides two levels of convenience. Use r_asm_assemble(()) when you need multi-line assembly, directive handling or want a RAsmCode result with both bytes and the produced assembly text. For single-line or binding-specific assembly callbacks use the lower-level encode callbacks that plugins expose. If you only need a raw buffer of bytes from a textual instruction, the utility r_asm_from_string(())

    /* Assembly API (prototypes) */
    RAsmCode* r_asm_assemble (RAsm *a, const char *buf);
    ut8 *r_asm_from_string (RAsm *a, ut64 addr, const char *b, int *l);
    void r_asm_code_free (RAsm *acode);

The assembler honors directives embedded in the input (such as .bits, .arch, or .endian) and uses the configured parser plugin to support pseudo-instructions.

    /* assemble several instructions and inspect bytes */
    RAsmCode *code = r_asm_assemble (a, "mov rax, 42op");
    if (code) {
        for (int i = 0; i < code->len; i++) {
            printf ("%02x ", code->bytes[i]);
        }
        printf ("%s, code->assembly);
        r_asm_code_free (code);
    }
    /* get a plain buffer (useful for embedding into other APIs) */
    int len;
    ut8 *buf = r_asm_from_string (a, 0x1000, "add eax, 1", &len);
    if (buf) { free (buf); }

DISASSEMBLY
There are two complementary disassembly APIs. The low-level r_asm_disassemble(()) RAnalOp r_asm_mdisassemble(()) RAsmCode

    /* Disassembly API (prototypes) */
    int r_asm_disassemble (RAsm *a, RAnalOp *op, const ut8 *buf, int len);
    RAsmCode* r_asm_mdisassemble (RAsm *a, const ut8 *buf, int len);
    char *r_asm_tostring (RAsm *a, ut64 addr, const ut8 *b, int l);
    RAsmCode* r_asm_mdisassemble_hexstr (RAsm *a, RParse *p, const char *hexstr);
    void r_asm_op_init (RAnalOp *op);
    void r_asm_op_fini (RAnalOp *op);

The typical decoding loop used in rasm2 and other tools calls r_asm_disassemble(()) repeatedly, updates the PC via r_asm_set_pc((),) and finalizes each RAnalOp with r_asm_op_fini(().)

    /* decode a buffer instruction-by-instruction */
    RAnalOp op;
    int off = 0;
    while (off < buflen) {
        r_asm_op_init (&op);
        r_asm_set_pc (a, base_addr + off);
        int sz = r_asm_disassemble (a, &op, buf + off, buflen - off);
        if (sz <= 0) { break; }
        printf ("%s, op.mnemonic);
        off += op.size;
        r_asm_op_fini (&op);
    }

For quick textual conversion of a byte buffer use r_asm_tostring(()) or r_asm_mdisassemble(()) ; to parse a hex string and optionally run the pseudo-assembly parser pass use r_asm_mdisassemble_hexstr(().)

PARSING
The assembler includes a lightweight parse/filter layer used to transform or annotate the produced assembly. The RParse r_asm_use_parser(().)

    /* Parsing API (prototypes) */
    RParse *r_parse_new (void);
    void r_parse_free (RParse *p);
    bool r_asm_use_parser (RAsm *a, const char *name);
    char *r_asm_parse_pseudo (RAsm *a, const char *data);

Common usage patterns are: run r_asm_mdisassemble_hexstr(()) with an RParse instance to post-process a hex string, or call r_asm_parse_pseudo(()) on a previously decoded mnemonic to get a human-friendly representation (for example replacing memory operands with symbolic names). Example:

    RParse *p = r_parse_new();
    p->pseudo = true; /* enable pseudo transformations */
    RAsmCode *c = r_asm_mdisassemble_hexstr (a, p, "4868 2a000000");
    if (c) { printf ("%s, c->assembly); r_asm_code_free (c); }
    r_parse_free (p);

EXAMPLES
Below are short examples that mirror patterns used across the codebase (see (libr/main/rasm2.c) and (libr/core/cmd_print.inc.c) for complete usages).

Assemble multiple lines and print the encoded bytes:

    RAsmCode *ac = r_asm_assemble (a, ".bits 64ov rax, 42op");
    if (ac) {
        for (int i = 0; i < ac->len; i++) printf ("%02x", ac->bytes[i]);
        r_asm_code_free (ac);
    }

Assemble and analyze instructions producing ESIL (pattern used by the r2 commands that print analysis):

    RAsmCode *acode = r_asm_assemble (a, "mov rax, 42dd rax, 1");
    if (acode) {
        RAnalOp aop = {0};
        int printed = 0;
        while (printed < acode->len) {
            aop.size = 0;
            if (r_anal_op (anal, &aop, base_addr, acode->bytes + printed, acode->len - printed,
                           R_ARCH_OP_MASK_ESIL) > 0) {
                printf ("%s, R_STRBUF_SAFEGET (&aop.esil));
            }
            printed += aop.size;
            r_anal_op_fini (&aop);
        }
        r_asm_code_free (acode);
    }

Disassemble a hex string and run the pseudo-parser (as used by the print command):

    RParse *p = r_parse_new();
    p->pseudo = true;
    RAsmCode *c = r_asm_mdisassemble_hexstr (a, p, "4868 2a000000");
    if (c) { puts (c->assembly); r_asm_code_free (c); }
    r_parse_free (p);

SEE ALSO
r_arch(3), r_anal(3), r_core(3)