⚡ ActionScript & Core Language

SWF Bytecode & Reverse Engineering: ABC Instructions & the Tamarin AVM2 Virtual Machine

👤 Author: Lead ActionScript & WebAssembly Architect📅 Technical Review: September 2026⚡ WebAssembly & WebGL 2.0 Verified

To modern software engineers accustomed to textual JavaScript bundles, compiled Adobe Flash applications often appear as opaque black boxes. However, inside every ActionScript 3.0 SWF lies ActionScript Byte Code (ABC)—a highly structured, stack-based bytecode format executed by the open-source Tamarin ActionScript Virtual Machine 2 (AVM2). Understanding SWF bytecode mechanics is essential for recovering lost source code, reversing obfuscated binaries, and engineering automated TypeScript transpilation pipelines.

1. The ABC File Format: Structure of a DoABC Tag

ActionScript 3.0 bytecode is packaged into an SWF within DoABC (Tag ID 72) or DoABC2 (Tag ID 82) tags. The binary payload follows a strict specification defined in Adobe's AVM2 overview:

  • Version Header: 16-bit minor version (typically 16) and 16-bit major version (typically 46).
  • Constant Pool (cpool_info): The central symbol table storing integer, unsigned integer, double-precision float, string, namespace, namespace set, and Multiname entries.
  • Method Signatures (method_info): Defines return types, parameter types, method names, and flags (such as NEED_REST or NEED_ARGUMENTS).
  • Class & Trait Metadata (metadata_info & class_info): Records class inheritance, implemented interfaces, constructor pointers, and static/instance member trait slots.
  • Method Bodies (method_body_info): Contains the active bytecode instructions, local register counts, evaluation stack limits, exception handler tables, and trait definitions.

2. The Tamarin AVM2 Stack Machine & Bytecode Instructions

The AVM2 virtual machine is a stack machine: computational instructions pop arguments from the evaluation stack and push results. AVM2 provides over 150 unique opcodes optimized for object-oriented programming:

// Disassembled AVM2 Bytecode: Calculating Pythagorean Distance
// AS3: return Math.sqrt(dx * dx + dy * dy);
getlocal_1             // Push local variable dx (Register 1)
getlocal_1             // Push local variable dx
multiply               // Pop both, multiply -> push (dx * dx)
getlocal_2             // Push local variable dy (Register 2)
getlocal_2             // Push local variable dy
multiply               // Pop both, multiply -> push (dy * dy)
add                    // Pop both products, sum -> push (dx*dx + dy*dy)
getlex      Math       // Push global Math class object
swap                   // Swap Math and sum on evaluation stack
callproperty sqrt, 1   // Invoke Math.sqrt with 1 argument
returnvalue            // Return result from method

AVM2's property resolution relies on Multinames—a qualified name paired with one or more namespaces. This enabled Flash to enforce package-private, internal, and custom user-defined namespaces at the virtual machine level.

3. Instruction Reference: Common AVM2 Bytecode Opcodes

Opcode Mnemonic Byte Value (Hex) Execution Behavior
getlocal_0 – getlocal_3 0xD0 – 0xD3 Pushes the value of register 0–3 onto the stack (register 0 is always this).
setlocal_1 – setlocal_3 0xD5 – 0xD7 Pops the top value from the stack and stores it into local register 1–3.
constructprop 0x4A Instantiates a class constructor with arg_count arguments from stack.
lookupswitch 0x1B Implements fast table-based switch statements via branch target offset tables.
coerce_a / coerce_s 0x82 / 0x85 Forces type coercion of top stack value to any or String.

4. Decompilation Pipelines & Control Flow Graph (CFG) Reconstruction

Converting flat linear bytecode back into high-level structured control statements requires decompilation software (such as JPEXS Free Flash Decompiler or RABCDAsm) to execute multi-stage graph analysis:

  • Basic Block Partitioning: The bytecode stream is partitioned into basic blocks—sequences of instructions with a single entry point and a single exit branch.
  • Control Flow Graph (CFG): Branch target addresses (iftrue, iffalse, jump) form directed edges between basic blocks.
  • Loop Detection & Structuring: Dominator tree analysis identifies loop back-edges, converting low-level jumps into structured while, for, and do-while blocks.
  • Type Inference & Register Recovery: Registers assigned inside loops are traced to deduce variable scoping and eliminate compiler-generated temporary storage variables.

5. Automated Bytecode-to-TypeScript Transpilation

Rather than relying on manual source code rewrites, modern enterprise migration engines parse the ABC bytecode directly into a modern TypeScript AST:

// Transpiled Modern TypeScript Output (Generated from AVM2 Bytecode)
export class GameEntity {
  public x: number = 0.0;
  public y: number = 0.0;
  protected health: number = 100;

  constructor(initialX: number, initialY: number) {
    this.x = initialX;
    this.y = initialY;
  }

  public takeDamage(amount: number): boolean {
    this.health = Math.max(0, this.health - amount);
    return this.health > 0;
  }
}

This automated transpilation guarantees 100% preservation of mathematical algorithms, physics collision equations, and business rules, enabling rapid deployment onto modern web architectures.

Frequently Asked Questions

What is an ActionScript Byte Code (ABC) block inside a compiled SWF binary?

Inside a compiled Flash SWF file, ActionScript 3.0 code is stored within DoABC or DoABC2 binary tags (Tag IDs 72 and 82). An ABC block encapsulates the complete executable program: constant pools (integers, floats, strings, namespaces, multinames), method signatures, class and trait definitions, and raw bytecode instruction arrays for the ActionScript Virtual Machine 2 (AVM2).

What was Project Tamarin, and what was its relationship to Mozilla and Adobe?

Project Tamarin was an open-source initiative launched in 2006 when Adobe open-sourced the core ActionScript Virtual Machine 2 (AVM2) codebase to the Mozilla Foundation. Tamarin implemented a high-performance, JIT-compiling virtual machine based on the draft ECMAScript 4 specification, with the original goal of unifying the Flash runtime and Firefox's SpiderMonkey JavaScript engine under a common high-speed execution core.

How does the AVM2 stack machine execute bytecode instructions?

AVM2 is a stack-based virtual machine: operands are pushed onto an evaluation stack and popped off by computational operations. Key instruction categories include: Push operations (pushint, pushstring, pushbyte); Local register access (getlocal_0 through getlocal_3, setlocal_1); Arithmetic (add, subtract, multiply); Property access (getproperty, setproperty with late-bound Multinames); Class instantiation (constructprop, newobject); and Control flow jumps (ifeq, ifne, jump, lookupswitch).

How do reverse engineering decompilers reconstruct high-level ActionScript source from ABC bytecode?

Decompilers like JPEXS Free Flash Decompiler (FFDec) and RABCDAsm parse the raw ABC binary stream into an Abstract Syntax Tree (AST). They construct a Control Flow Graph (CFG) from branch jump targets, analyze variable lifetimes to convert local register accesses back into named variables, resolve Multiname constant pool references into class property names, and synthesize structured control structures (if-else, while, for loops) from raw assembly jump offsets.

How do modern migration pipelines automate ABC bytecode translation into TypeScript?

Modern enterprise migration pipelines utilize automated transpilers that parse ABC bytecode directly into a TypeScript AST. The compiler maps AS3 sealed classes to TypeScript classes, preserves nominal type interfaces, converts Vector. typed arrays into JavaScript typed arrays, and translates AVM2 event listener registrations into modern standard event patterns without requiring manual source-code rewrites.

Recover & Transpile Your Legacy Flash Bytecode

Lost your original ActionScript source code? CodeForFlash specializes in deep AVM2 bytecode reverse engineering, deobfuscation, and automated bytecode-to-TypeScript transpilation.

Request a Bytecode Reverse Engineering Audit →
CodeForFlash Technical Council

Written by CodeForFlash Technical Council

Senior interactive systems architect and digital preservation engineer specializing in ActionScript 3.0 virtual machines (AVM2), Rust/WebAssembly emulation engines (Ruffle), Stage3D to WebGL 2.0 shader compilation, and HTML5 vector rasterization.