AVM1, the ActionScript Virtual Machine 1, runs the code of ActionScript 1.0 and ActionScript 2.0, and the simpler actions of Flash 3 and 4 before them. It is a stack machine that runs lists of actions. A CWS movie is SWF 6 or later, so it may use every action below, those of SWF 7 included. In a movie whose FileAttributes sets ActionScript3, the player ignores every action list. How each kind of ActionScript source compiles to these actions is described in ActionScript in SWF.
Where action lists are
- DoAction (12): frame scripts on the main timeline and in sprites
- DoInitAction (59):
#initclipblocks and compiled ActionScript 2 classes - DefineButton (7): after the button records
- DefineButton2 (34): in each BUTTONCONDACTION
- PlaceObject2 and PlaceObject3: in each clip action record
Every list ends with an End action (0x00).
DoAction (12)
| Type | Name | Description |
|---|---|---|
| ACTIONRECORD[] | Actions | Run when the frame is shown, ending with an End action |
DoInitAction (59)
| Type | Name | Description |
|---|---|---|
| UI16 | SpriteID | The sprite these actions belong to |
| ACTIONRECORD[] | Actions | Run once, before the sprite is first used, ending with an End action |
SWF 6. Flash writes each ActionScript 2 class as a DoInitAction on an empty sprite it
exports as __Packages. and the class name, so the class is defined before
the first frame runs.
The action record
| Type | Name | Description |
|---|---|---|
| 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 a reader can always step over an action it does not know.
Branches and owned blocks
- ActionJump and ActionIf hold an SI16 BranchOffset, counted in bytes from the start of the next action, the end of the branch action.
- ActionWaitForFrame and ActionWaitForFrame2 skip a number of actions, not bytes.
- ActionDefineFunction and ActionDefineFunction2 end with a UI16 codeSize: the function body is the next codeSize bytes of actions after the record. ActionWith’s Size and ActionTry’s TrySize, CatchSize and FinallySize count their blocks after the record the same way. These bodies have no End action of their own.
Registers
There are four global registers, 0 to 3, for ActionStoreRegister and push type 4. Inside an ActionDefineFunction2 body there are up to 255 local registers.
ActionPush values
One ActionPush can push several values, each a UI8 Type and then the value:
| Type | Value | SWF |
|---|---|---|
| 0 | STRING | 4 |
| 1 | FLOAT, 32 bits | 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 (shown signed) | 5 |
| 8 | UI8 constant pool index | 5 |
| 9 | UI16 constant pool index | 5 |
ActionConstantPool
UI16 Count, then Count STRINGs. Push types 8 and 9 index the pool most recently defined by an executed ActionConstantPool. Compilers put one at the start of each action list to shorten repeated names.
ActionDefineFunction
STRING FunctionName (empty for an anonymous function, which is then pushed), UI16 NumParams, NumParams STRINGs (the parameter names), UI16 codeSize.
ActionDefineFunction2
| Type | Name | Description |
|---|---|---|
| STRING | FunctionName | Empty for an anonymous function |
| UI16 | NumParams | The number of parameters |
| UI8 | RegisterCount | Local registers to allocate |
| UB[1] × 8 | flags | PreloadParentFlag, PreloadRootFlag, SuppressSuperFlag, PreloadSuperFlag, SuppressArgumentsFlag, PreloadArgumentsFlag, SuppressThisFlag, PreloadThisFlag |
| UB[7], UB[1] | Reserved, PreloadGlobalFlag | |
| REGISTERPARAM × NumParams | Parameters | Each UI8 Register (0 for a named variable) and STRING ParamName |
| UI16 | codeSize | The body’s length in bytes |
The preloaded values take registers from 1 in this order: this, arguments, super, _root, _parent, _global, each only if its Preload flag is set. “Suppress” means the value is not created at all. Flash MX 2004 and later compile functions this way when they target SWF 7 or later, so registers replace named locals.
ActionTry
UB[5] Reserved, UB[1] CatchInRegisterFlag, UB[1] FinallyBlockFlag, UB[1] CatchBlockFlag; UI16 TrySize, UI16 CatchSize, UI16 FinallySize; then STRING CatchName or, with CatchInRegisterFlag, UI8 CatchRegister; then the try, catch and finally blocks.
ActionWith
UI16 Size, then a block of that many bytes run with the popped object on the scope chain.
ActionGetURL2 and ActionGotoFrame2
ActionGetURL2: 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.
ActionGotoFrame2: UB[6] Reserved, UB[1] SceneBiasFlag, UB[1] PlayFlag, then UI16 SceneBias if flagged.
Property indexes
ActionGetProperty and ActionSetProperty name a property by number: 0 _x, 1 _y, 2 _xscale, 3 _yscale, 4 _currentframe, 5 _totalframes, 6 _alpha, 7 _visible, 8 _width, 9 _height, 10 _rotation, 11 _target, 12 _framesloaded, 13 _name, 14 _droptarget, 15 _url, 16 _highquality, 17 _focusrect, 18 _soundbuftime, 19 _quality, 20 _xmouse, 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, an inference from DefineButton being SWF 1. On the stack, A is the value popped first and B the one below it.
| Code | Action | SWF | Operands or 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, B; pushes B + A (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, string; pushes the substring |
| 0x17 | ActionPop | 4 | Pops a value |
| 0x18 | ActionToInteger | 4 | Converts to an integer |
| 0x1C | ActionGetVariable | 4 | Pops a name, pushes its value |
| 0x1D | ActionSetVariable | 4 | Pops a value and a name, sets the variable |
| 0x20 | ActionSetTarget2 | 4 | Pops a target path |
| 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 |
| 0x24 | ActionCloneSprite | 4 | Pops depth, target, source |
| 0x25 | ActionRemoveSprite | 4 | Pops a target |
| 0x26 | ActionTrace | 4 | Pops a value and sends it to the debugger |
| 0x27 | ActionStartDrag | 4 | Pops target, lock, constrain (and a rectangle) |
| 0x28 | ActionEndDrag | 4 | Stops dragging |
| 0x29 | ActionStringLess | 4 | Pops two strings, pushes whether the second sorts first |
| 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 | Pops a constructor, a count and interfaces |
| 0x2D | ActionFSCommand2 | Flash Lite | An fscommand2 call; not in the specification |
| 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 arguments; pushes the result |
| 0x3E | ActionReturn | 5 | Returns the top value |
| 0x3F | ActionModulo | 5 | Pushes B mod A |
| 0x40 | ActionNewObject | 5 | Pops a name, a count and arguments; constructs an object |
| 0x41 | ActionDefineLocal2 | 5 | Pops a name, defines an undefined local |
| 0x42 | ActionInitArray | 5 | Pops a count and 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 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 arguments; pushes the result |
| 0x53 | ActionNewMethod | 5 | Pops a name, an object, a count and arguments; constructs with the method |
| 0x54 | ActionInstanceOf | 6 | Pops a constructor and an object, pushes whether it is an instance |
| 0x55 | ActionEnumerate2 | 6 | Pops an object, pushes null then its property names |
| 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 |
| 0x66 | ActionStrictEquals | 6 | Equality without type conversion (===) |
| 0x67 | ActionGreater | 6 | ECMA-262 greater than |
| 0x68 | ActionStringGreater | 6 | Pops two strings, pushes whether the second sorts after |
| 0x69 | ActionExtends | 7 | Pops a superclass and a subclass constructor, sets up inheritance |
| 0x81 | ActionGotoFrame | 3 | UI16 Frame (from 0) |
| 0x83 | ActionGetURL | 3 | STRING UrlString, STRING TargetString |
| 0x87 | ActionStoreRegister | 5 | UI8 RegisterNumber: copies the top value into it |
| 0x88 | ActionConstantPool | 5 | UI16 Count, STRING × Count (above) |
| 0x89 | ActionStrictMode | † | UI8 mode; undocumented, the name JPEXS uses |
| 0x8A | ActionWaitForFrame | 3 | UI16 Frame, UI8 SkipCount |
| 0x8B | ActionSetTarget | 3 | STRING TargetName |
| 0x8C | ActionGoToLabel | 3 | STRING Label |
| 0x8D | ActionWaitForFrame2 | 4 | UI8 SkipCount; pops the frame |
| 0x8E | ActionDefineFunction2 | 7 | Above |
| 0x8F | ActionTry | 7 | Above |
| 0x94 | ActionWith | 5 | UI16 Size (above) |
| 0x96 | ActionPush | 4 | Typed values (above) |
| 0x99 | ActionJump | 4 | SI16 BranchOffset |
| 0x9A | ActionGetURL2 | 4 | Flags (above) |
| 0x9B | ActionDefineFunction | 5 | Above |
| 0x9D | ActionIf | 4 | SI16 BranchOffset; pops the condition |
| 0x9E | ActionCall | 4 | Pops a frame and runs its actions |
| 0x9F | ActionGotoFrame2 | 4 | Flags, UI16 SceneBias (above) |
Any other code is not an action the specification defines. The explorer shows it as “Unknown action” with its operands, and carries on.
An action list, byte by byte
The bytes of actions are the same in every SWF. This frame script, from an SWF 4
movie examined for this site, is xangle = xangle + 5 as Flash 4 compiled
it:
96 08 00 00 78 61 6E 67 6C 65 00
96 08 00 00 78 61 6E 67 6C 65 00
1C
96 03 00 00 35 00
0A
1D
96 08 00: ActionPush with 8 bytes of operands;00, type 0, a string;78 61 6E 67 6C 65 00, "xangle".- The same again, then
1CActionGetVariable: the value ofxanglereplaces the second name. 96 03 00 00 35 00: push the string "5". Flash 4 pushed numbers as strings.0AActionAdd, then1DActionSetVariable stores the sum inxangle.