DynASM advertises itself as a dynamic assembler for code generation engines. I can think of several interpretations of what a dynamic assembler might be, not all of which are compatible with each other. As such, it is worth beginning my series about DynASM with a description of what it is and what it isn't.

The envisioned usage pattern is to have fragments of assembly code which are syntactically complete, except possibly for the values of some constants (i.e. the instructions, addressing modes, and registers are all fixed). A decision is made at runtime as to how many copies to make of each fragment, what the value of each constant should be in each fragment, and in what order to emit the fragments.

The DynASM site states that DynASM takes mixed C/Assembler source as input, and produces plain C code output. While this is true, it is also easy to misinterpret: the input to DynASM is a C file whose intended purpose is to emit machine code - the assembly portion of the input is the code to emit rather than the code to run in-line with the C portion. As an example, the intent of the following code is that when write_return_n is called, the machine code for return n; is emitted:

void write_return_n(dasm_state ds, int n)
{
| mov rax, n
| ret
}

If DynASM was implemented by building up a string of assembly code and then passing the result to a stand-alone assembler, then the result of passing the above code through DynASM might be:

void write_return_n(dasm_state ds, int n)
{
  ds += "mov rax, " + n + "\n";
  ds += "ret\n";
}

In reality, DynASM builds up a string of machine code rather than a string of assembly code, meaning that the actual output is somewhat closer to the following:

void write_return_n(dasm_state ds, int n)
{
  dasm_append_bytes(ds, 0x48, 0xC7, 0xC0); dasm_append_dword(ds, n);
  dasm_append_bytes(ds, 0xC3);
}

With this example in mind, DynASM can be described as a text-processing tool which takes lines starting with a vertical bar, interprets them as assembly code, and replaces them with C code which writes out the corresponding machine code. This description fails to mention a bunch of really nice features, but it gives the general idea.