Scroll to navigation

R_ASM(3) Library Functions Manual R_ASM(3)

NAME

r_asmAssembler 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 (()) 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 (()) 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 (()) or the lower-level encode callbacks that plugins expose. If you only need a raw buffer of bytes from a textual instruction, the utility (())

/* Assembly API (prototypes) */
RAsmCode* r_asm_massemble (RAsm *a, const char *buf);
RAsmCode* r_asm_rasm_assemble (RAsm *a, const char *buf, bool use_spp);
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 , , )
/* assemble several instructions and inspect bytes */
RAsmCode *code = r_asm_massemble (a, "mov rax, 420op");
if (code) {
    for (int i = 0; i < code->len; i++) {
        printf ("%02x ", code->bytes[i]);
    }
    printf ("%s0, 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 (()) RAnalOp (()) 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 (()) repeatedly, updates the PC via ((),) and finalizes each RAnalOp with (().)
/* 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 ("%s0, op.mnemonic);
    off += op.size;
    r_asm_op_fini (&op);
}

For quick textual conversion of a byte buffer use (()) 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 (().)

/* 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 (()) with an RParse instance to post-process a hex string, or call (()) 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 ("%s0, 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_massemble (a, ".bits 640ov rax, 420op");
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_massemble (a, "mov rax, 420dd 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 ("%s0, 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)

September 21, 2025 Debian