NationalSecurityAgency/ghidra · error · AssemblyException

Could not assemble: %s

Error message

Could not assemble: %s

What it means

Thrown by AbstractPatchAssemblyCommand.assemble() when AssemblyBuffer.assemble(line) fails for one instruction line. The original AssemblySyntaxException (malformed/unknown mnemonic or operand) or AssemblySemanticException (valid syntax but impossible encoding, e.g. bad register or out-of-range immediate) is wrapped in an AssemblyException whose message is 'Could not assemble: <line>'. Note: only raw instruction text is supported here; the source comment marks data directives and label placement as unimplemented.

Source

Thrown at Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/AbstractPatchAssemblyCommand.java:74

	public AddressSetView assemble(T program, TaskMonitor monitor)
			throws CancelledException, IOException, MemoryAccessException, AssemblyException {
		monitor.setMessage("Constructing Assembler");
		monitor.checkCancelled();
		AssemblyBuffer buf = new AssemblyBuffer(asm, entry, initialContext);

		monitor.initialize(lines.size(), "Assembling");
		for (String line : lines) {
			if (line.isBlank()) {
				continue;
			}
			// LATER: Data directives? Label placement?
			try {
				buf.assemble(line);
				monitor.increment();
			}
			catch (AssemblySyntaxException | AssemblySemanticException e) {
				throw new AssemblyException("Could not assemble: %s".formatted(line), e);
			}
		}

		monitor.initialize(0, "Placing bytes");
		monitor.checkCancelled();
		AddressSet set = new AddressSet(entry, buf.getNext().previous());
		// Get the command before we modify the memory/listing, so it can inspect things
		Command<T> dis = newDisassembleCommand(set, program);

		program.getListing()
				.clearCodeUnits(set.getMinAddress(), set.getMaxAddress(), true, monitor);
		program.getMemory().setBytes(entry, buf.getBytes());

		monitor.setMessage("Disassembling");
		monitor.checkCancelled();

		// Might not succeed...
		dis.applyTo(program);

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Read the offending line from the message after 'Could not assemble: ' and correct the typo / operand count.
  2. Confirm the instruction is valid for the program's processor language and that the assembler was built for that language (Assemblers.getAssemblerForLanguage(program.getLanguage())).
  3. Switch the operand/register to a form the language encodes (e.g. different immediate width, valid register name, supported addressing mode); consult the Sleigh / processor reference.
  4. Split multi-instruction input into one line per instruction and assemble line-by-line to isolate which line fails, since the exception reports only the first failing line.
  5. If no line assembles at all, the language may lack an assembler spec; verify the language ships assembly templates before attempting patch assembly.

Example fix

// before - typo + wrong-syntax instruction for the target language
String bad = "mvo rax, 0x1";  // 'mvo' is not a valid mnemonic

// after - correct mnemonic and operands for x86:LE:64:default
String good = "mov rax, 0x1";
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-assemble each line into a throwaway AssemblyBuffer before
// committing patches to the real program, to localize the failure.
AssemblyBuffer probe = new AssemblyBuffer(asm, entry, initialContext);
java.util.List<String> problems = new java.util.ArrayList<>();
for (String line : lines) {
    if (line.isBlank()) continue;
    try {
        probe.assemble(line);
    } catch (AssemblySyntaxException | AssemblySemanticException e) {
        problems.add(line + "  <- " + e.getMessage());
    }
}

Try / catch

// applyTo() already catches AssemblyException and stores its message in
// status (command returns false). For direct assemble() use, catch
// AssemblyException and read the offending line from the message.
try {
    cmd.assemble(program, monitor);
} catch (AssemblyException e) {
    String msg = e.getMessage();           // "Could not assemble: <line>"
    String line = msg.substring(msg.indexOf(':') + 1).trim();
    Throwable cause = e.getCause();        // AssemblySyntax|SemanticException
    // surface line + cause to the user; do NOT silently retry unchanged input
}

Prevention

When it happens

Trigger: Calling the patch assembler (single-line or multi-line) where at least one line is: an unknown/unsupported mnemonic for the program's processor/Sleigh language, has the wrong number of operands, references a register that does not exist for the language, uses an immediate outside the encodable range, uses the wrong assembly syntax for the architecture, or contains a label/data directive the assembler does not understand.

Common situations: Typo in an instruction; pasting x86 syntax into an ARM (or vice versa) program; using AT&T vs Intel form when the language expects the other; an instruction the Sleigh assembler does not encode for that language variant; encoding-dependent operand (e.g. conditional suffix, addressing mode) not supported; whitespace/blank handling confusion (note: truly blank lines are skipped).

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/8bb710ce2a399520. Report an issue: GitHub.