AVM1 is the virtual machine of Flash’s scripts: a stack machine that runs lists of actions. Every action is a one-byte code, and actions from 0x80 up carry operands. In this format it grew in three steps. The first actions, called the SWF 3 actions, control the timeline: play, stop, go to a frame, load a URL. SWF 4 added a stack, variables, arithmetic and string handling, pushing every number as a string. SWF 5 added Flash 5’s ActionScript: objects, functions, registers and the constant pool. Strings in actions are in the player’s code page.
Where action lists are
- DoAction – frame scripts, on the main timeline and in sprites (SWF 3)
- DefineButton – one list after the button records, run on release
- DefineButton2 – a list in each condition action (SWF 3)
- PlaceObject2 – a list in each clip action record (SWF 5)
Every list ends with an End action, 0x00.
DoAction (12, SWF 3)
| Type | Name | Meaning |
|---|---|---|
| ACTIONRECORD[] | Actions | The frame’s actions, ending with End |
The actions run when the frame they belong to is complete.
The action record
| Type | Name | Meaning |
|---|---|---|
| UI8 | ActionCode | The action |
| UI16 | Length | Only if ActionCode is 0x80 or more: the bytes of operands that follow |
| bytes | operands | Length bytes |
Actions below 0x80 have no operands and no length. So an action a reader does not know can always be stepped over.
Branches
ActionJump and ActionIf hold an SI16 BranchOffset, counted in bytes from the start of the next action, the end of the branch action itself. ActionWaitForFrame and ActionWaitForFrame2 skip a number of actions, not bytes.
Owned blocks
ActionDefineFunction ends with a UI16 codeSize: the function’s body is the next codeSize bytes of actions after the record. ActionWith’s Size counts the block after the record in the same way. These bodies have no End action of their own.
Registers
SWF 5 has four registers, 0 to 3, for ActionStoreRegister and push type 4.
ActionPush (0x96, SWF 4)
Pushes one or more values. Each is a UI8 type, then the value:
| Type | Value | SWF |
|---|---|---|
| 0 | STRING | 4 |
| 1 | FLOAT, 32-bit | 4 |
| 2 | null (no bytes) | 5 |
| 3 | undefined (no bytes) | 5 |
| 4 | UI8 register number | 5 |
| 5 | UI8 boolean | 5 |
| 6 | DOUBLE: the high 32 bits first, each half little-endian | 5 |
| 7 | UI32 integer, used as signed | 5 |
| 8 | UI8 constant pool index | 5 |
| 9 | UI16 constant pool index | 5 |
Flash 4 wrote numbers as strings, type 0, and converted them when an arithmetic action ran.
ActionConstantPool (0x88, SWF 5)
UI16 Count, then Count STRINGs. Push types 8 and 9 index the pool most recently set by an ActionConstantPool that has run. Compilers put one at the start of each action list, so that repeated names are stored once.
ActionDefineFunction (0x9B, SWF 5)
| Type | Name | Meaning |
|---|---|---|
| STRING | FunctionName | Empty for an anonymous function, which is then pushed |
| UI16 | NumParams | The number of parameters |
| STRING × NumParams | param | Their names |
| UI16 | codeSize | The bytes of the body after this record |
ActionWith (0x94, SWF 5)
UI16 Size, then a block of Size bytes, run with the popped object added to the scope chain.
ActionGetURL2 (0x9A, SWF 4)
One byte of flags: UB[2] SendVarsMethod (0 none, 1 GET, 2 POST), UB[4] Reserved, UB[1] LoadTargetFlag (0 a browser window, 1 a sprite path), UB[1] LoadVariablesFlag. The URL and the target are popped from the stack.
ActionGotoFrame2 (0x9F, SWF 4)
UB[6] Reserved, UB[1] SceneBiasFlag, UB[1] PlayFlag, then UI16 SceneBias if the flag is set. The frame, a number or a label, is popped from the stack.
Property indexes
ActionGetProperty and ActionSetProperty take a property by number:
| Index | Property | Index | Property |
|---|---|---|---|
| 0 | _x | 11 | _target |
| 1 | _y | 12 | _framesloaded |
| 2 | _xscale | 13 | _name |
| 3 | _yscale | 14 | _droptarget |
| 4 | _currentframe | 15 | _url |
| 5 | _totalframes | 16 | _highquality |
| 6 | _alpha | 17 | _focusrect |
| 7 | _visible | 18 | _soundbuftime |
| 8 | _width | 19 | _quality |
| 9 | _height | 20 | _xmouse |
| 10 | _rotation | 21 | _ymouse |
All actions
The SWF column is the version the specification gives. Its “SWF 3” actions were in SWF 1 and 2 buttons already, which is an inference from DefineButton being SWF 1. For two-operand actions, A is the value popped first, from the top of the stack, and B the one below it.
| Code | Name | SWF | Operands and stack |
|---|---|---|---|
| 0x00 | End | 1 | Ends the action list |
| 0x04 | ActionNextFrame | 3 | Goes to the next frame |
| 0x05 | ActionPreviousFrame | 3 | Goes to the previous frame |
| 0x06 | ActionPlay | 3 | Starts playing |
| 0x07 | ActionStop | 3 | Stops playing |
| 0x08 | ActionToggleQuality | 3 | Switches between high and low quality |
| 0x09 | ActionStopSounds | 3 | Stops all sounds |
| 0x0A | ActionAdd | 4 | Pops A and B, pushes B + A as numbers |
| 0x0B | ActionSubtract | 4 | Pushes B − A |
| 0x0C | ActionMultiply | 4 | Pushes B × A |
| 0x0D | ActionDivide | 4 | Pushes B ÷ A |
| 0x0E | ActionEquals | 4 | Numeric equality |
| 0x0F | ActionLess | 4 | Pushes B < A |
| 0x10 | ActionAnd | 4 | Logical and |
| 0x11 | ActionOr | 4 | Logical or |
| 0x12 | ActionNot | 4 | Logical not |
| 0x13 | ActionStringEquals | 4 | Pops two strings, pushes whether they are equal |
| 0x14 | ActionStringLength | 4 | Pops a string, pushes its length |
| 0x15 | ActionStringExtract | 4 | Pops count, index and string; pushes the substring |
| 0x17 | ActionPop | 4 | Discards the top value |
| 0x18 | ActionToInteger | 4 | Converts the top value to an integer |
| 0x1C | ActionGetVariable | 4 | Pops a name, pushes the variable’s value |
| 0x1D | ActionSetVariable | 4 | Pops a value and a name, sets the variable |
| 0x20 | ActionSetTarget2 | 4 | Pops a target path and makes it the current target |
| 0x21 | ActionStringAdd | 4 | Pops two strings, pushes them joined |
| 0x22 | ActionGetProperty | 4 | Pops an index and a target, pushes the property |
| 0x23 | ActionSetProperty | 4 | Pops a value, an index and a target, sets the property |
| 0x24 | ActionCloneSprite | 4 | Pops depth, target and source; duplicates a movie clip |
| 0x25 | ActionRemoveSprite | 4 | Pops a target, removes the duplicated clip |
| 0x26 | ActionTrace | 4 | Pops a value, sends it to the debugger |
| 0x27 | ActionStartDrag | 4 | Pops target, lock and constrain (and a rectangle if constrained); starts dragging |
| 0x28 | ActionEndDrag | 4 | Stops dragging |
| 0x29 | ActionStringLess | 4 | Pops two strings, pushes whether B sorts before A |
| 0x30 | ActionRandomNumber | 4 | Pops a maximum, pushes a random integer below it |
| 0x31 | ActionMBStringLength | 4 | String length in characters, for multibyte text |
| 0x32 | ActionCharToAscii | 4 | Pops a string, pushes the code of its first character |
| 0x33 | ActionAsciiToChar | 4 | Pops a code, pushes the character |
| 0x34 | ActionGetTime | 4 | Pushes the milliseconds since the movie started |
| 0x35 | ActionMBStringExtract | 4 | Substring in characters, for multibyte text |
| 0x36 | ActionMBCharToAscii | 4 | Character code, for multibyte text |
| 0x37 | ActionMBAsciiToChar | 4 | Character from a code, for multibyte text |
| 0x3A | ActionDelete | 5 | Pops a name and an object, deletes the property |
| 0x3B | ActionDelete2 | 5 | Pops a name, deletes the variable |
| 0x3C | ActionDefineLocal | 5 | Pops a value and a name, defines a local variable |
| 0x3D | ActionCallFunction | 5 | Pops a name, a count and the arguments; calls the function, pushes the result |
| 0x3E | ActionReturn | 5 | Returns from the function with the top value |
| 0x3F | ActionModulo | 5 | Pushes B mod A |
| 0x40 | ActionNewObject | 5 | Pops a name, a count and the arguments; constructs an object |
| 0x41 | ActionDefineLocal2 | 5 | Pops a name, defines an undefined local variable |
| 0x42 | ActionInitArray | 5 | Pops a count and the elements, pushes an array |
| 0x43 | ActionInitObject | 5 | Pops a count and name–value pairs, pushes an object |
| 0x44 | ActionTypeOf | 5 | Pops a value, pushes its type name |
| 0x45 | ActionTargetPath | 5 | Pops a movie clip, pushes its target path |
| 0x46 | ActionEnumerate | 5 | Pops a variable name, pushes null and then its property names |
| 0x47 | ActionAdd2 | 5 | ECMA-262 addition: numbers, or strings joined |
| 0x48 | ActionLess2 | 5 | ECMA-262 less-than |
| 0x49 | ActionEquals2 | 5 | ECMA-262 equality |
| 0x4A | ActionToNumber | 5 | Converts the top value to a number |
| 0x4B | ActionToString | 5 | Converts the top value to a string |
| 0x4C | ActionPushDuplicate | 5 | Pushes a copy of the top value |
| 0x4D | ActionStackSwap | 5 | Swaps the top two values |
| 0x4E | ActionGetMember | 5 | Pops a name and an object, pushes the property |
| 0x4F | ActionSetMember | 5 | Pops a value, a name and an object, sets the property |
| 0x50 | ActionIncrement | 5 | Adds 1 to the top value |
| 0x51 | ActionDecrement | 5 | Subtracts 1 from the top value |
| 0x52 | ActionCallMethod | 5 | Pops a name, an object, a count and the arguments; calls the method |
| 0x53 | ActionNewMethod | 5 | Pops a name, an object, a count and the arguments; constructs with the method |
| 0x60 | ActionBitAnd | 5 | Bitwise and of two 32-bit integers |
| 0x61 | ActionBitOr | 5 | Bitwise or |
| 0x62 | ActionBitXor | 5 | Bitwise exclusive or |
| 0x63 | ActionBitLShift | 5 | Shift left |
| 0x64 | ActionBitRShift | 5 | Signed shift right |
| 0x65 | ActionBitURShift | 5 | Unsigned shift right |
| 0x81 | ActionGotoFrame | 3 | UI16 Frame, counted from 0 |
| 0x83 | ActionGetURL | 3 | STRING UrlString, STRING TargetString |
| 0x87 | ActionStoreRegister | 5 | UI8 RegisterNumber: copies the top value into the register |
| 0x88 | ActionConstantPool | 5 | UI16 Count, STRING × Count |
| 0x8A | ActionWaitForFrame | 3 | UI16 Frame, UI8 SkipCount: if the frame is not loaded, skip that many actions |
| 0x8B | ActionSetTarget | 3 | STRING TargetName: makes a named movie clip the current target |
| 0x8C | ActionGoToLabel | 3 | STRING Label: goes to the labelled frame |
| 0x8D | ActionWaitForFrame2 | 4 | UI8 SkipCount; the frame is popped |
| 0x94 | ActionWith | 5 | UI16 Size; pops an object |
| 0x96 | ActionPush | 4 | Typed values |
| 0x99 | ActionJump | 4 | SI16 BranchOffset |
| 0x9A | ActionGetURL2 | 4 | Flags; pops URL and target |
| 0x9B | ActionDefineFunction | 5 | Name, parameter names, codeSize |
| 0x9D | ActionIf | 4 | SI16 BranchOffset; pops a condition and branches if it is true |
| 0x9E | ActionCall | 4 | Pops a frame and runs that frame’s actions |
| 0x9F | ActionGotoFrame2 | 4 | Flags, UI16 SceneBias; pops the frame |
Any other code is not defined in this format. The explorer shows it as an unknown action and steps over it by its length.
Actions and tags from later versions
SWF 6 and 7 added these for Flash MX and ActionScript 2.0. They have no place in a SWF 1 to 5 movie; the explorer still names them if it meets them.
| Code | Name | SWF | What it does |
|---|---|---|---|
| tag 59 | DoInitAction | 6 | A tag: UI16 SpriteID, then actions run once before the sprite is first used |
| 0x2A | ActionThrow | 7 | Pops a value and throws it |
| 0x2B | ActionCastOp | 7 | Pops an object and a constructor; pushes the object if it is an instance, else null |
| 0x2C | ActionImplementsOp | 7 | Declares the interfaces a constructor implements |
| 0x2D | ActionFSCommand2 | Flash Lite | An fscommand2 call; not in the SWF specification |
| 0x54 | ActionInstanceOf | 6 | Pops a constructor and an object, pushes whether it is an instance |
| 0x55 | ActionEnumerate2 | 6 | Pops an object, pushes null and then its property names |
| 0x66 | ActionStrictEquals | 6 | Equality without type conversion |
| 0x67 | ActionGreater | 6 | ECMA-262 greater-than |
| 0x68 | ActionStringGreater | 6 | Pops two strings, pushes whether B sorts after A |
| 0x69 | ActionExtends | 7 | Sets up inheritance between two constructors |
| 0x89 | ActionStrictMode † | – | UI8 mode; undocumented, the name JPEXS uses |
| 0x8E | ActionDefineFunction2 | 7 | A function whose parameters and this, arguments, super, _root, _parent and _global live in up to 255 registers |
| 0x8F | ActionTry | 7 | A try block with optional catch and finally blocks |
A worked example
The first actions in the DoAction of a Flash 4 movie, SWF 4:
00000020 96 08 00 00 78 61 6E 67 6C 65 00 96 08 00 00 78
00000030 61 6E 67 6C 65 00 1C 96 03 00 00 35 00 0A 1D
96 08 00: ActionPush with 8 bytes of operands: type 0, the string “xangle”. It is pushed twice.1C: ActionGetVariable pops “xangle” and pushes its value.96 03 00 00 35 00: push the string “5”. Flash 4 pushed numbers as strings.0A: ActionAdd pops “5” and the value and pushes their sum.1D: ActionSetVariable pops the sum and the name “xangle” and sets the variable.
xangle = xangle + 5;