Super happy unofficial Flash 5 actionscript bytecode speccy fun

The following is a list of opcodes added to the Flash bytecode interpreter in Flash 5. Obviously, this isn't a complete list, nor necessarily accurate. Count the number of ??'s if you have any doubts.

Please direct all comments, flames, spam, etc. to dave@opaque.net. And hey, while you're here, you might as well go check out ming, the ultraswank swf output library and php module.

A note about conventions used: following the grey bar listing the opcode and a brief description is the opcode syntax. If an opcode takes arguments, I've listed them to the right of the opcode. Items in <> brackets represent elemental types:

<byte> = 1 byte
<short> = 2 bytes
<int> = 4 bytes

Anything else is obvious, hopefully. Items listed to the left of the opcode are expected to be on the stack, in the given order. That is, the leftmost item should be deepest in the stack, while the item immediately left of the opcode should be on the top of the stack (most recently pushed). If the operation returns a value to the stack, it's listed after an arrow: ==>.

Also, instead of looking up ASCII values for letters, I've used the shorthand '_<char>'; e.g., the ASCII code for lower-case 'c' is represented by '_c'.

Everything clear? No? So sorry. Let's begin:

0x96 - push data

0x96 <short length> [data] ==> [data]

where [data] is one or more of

<byte type> [bytes]

type codes:

numbertype# of bytes
00Null-terminated stringstrlen+1
02NULL (?)0
03???0
04"register" (see below)1
05boolean (1=true, 0=false)1
06double8
07int4
08dictionary lookup (see op 0x88)1

e.g.,

96 0b 00 07 09 00 00 00 00 _b _l _a _h 00
   -len- ---number 9--- -----"blah"------

pushes two things: first the number 9 (type 7, int), then the string 'blah' (type 0, string).

The double type is in IEEE (?) floating point format, with top and lower four bytes swapped from big(?)-endian layout- i.e.,

double readDouble(FILE *f)
{
  char b[8];
  b[4] = readByte(f);
  b[5] = readByte(f);
  b[6] = readByte(f);
  b[7] = readByte(f);
  b[0] = readByte(f);
  b[1] = readByte(f);
  b[2] = readByte(f);
  b[3] = readByte(f);

  return *((double *)b);
}

reads in a double type on 32-bit intel machines.

The "register" type (4) is a temporary memory location, set with opcode 0x87.

0x88 - declare dictionary

0x88 <short length> <byte n> <byte ??> [list of n strings]

is a list of strings which can be pushed to the stack with a "type 8" push.

Ex: push three copies of the string "narf" to the stack: 88 07 00 01 00 _n _a _r _f 00 - dictionary entry 0 is "narf" 96 06 00 08 00 08 00 08 00 - pull dictionary entry 0 three times

I could have written just <short n> since the ?? part always seems to be 0, but since you can only access 256 entries (lookup index is only one byte), that wouldn't make any sense.. Hrm.

0x9b - declare function

0x9b <short length> <string name> <short nargs> [nargs strings] <short bytes>

bytes is the number of bytes which comprise the function. This number of bytes following the block are not executed, but stored as the definition of the function.

Ex.: define function square(a) { return a*a; } 9b 0d 00 _s _q _u _a _r _e 00 - define function, name "square" 01 00 - one argument _a 00 - argument is variable "a" 10 00 - following 16 bytes are the function code 96 03 00 00 _a 00 - push string "a" 1c - get value 96 03 00 00 _a 00 - push string "a" 1c - get value 0c - multiply 3e - return value

0x3d - call function

[data args] <int nargs> <string functionname> 0x3d ==> <function return value>

0x3e - return from function

<data returnvalue> 0x3e ==> <data returnvalue>

0x52 - call method

[data args] <int nargs> <object obj> <string methodname> 0x52 ==> <function return value>

Ex: trace(Math.sin(a)) 96 03 00 00 _a 00 - push string "a" 1C - get value of "a" 96 0c 00 07 01 00 00 00 00 - push int 1 00 _M _a _t _h 00 - and string "Math" 1C - get value of "Math", the Math object 96 05 00 00 _s _i _n 00 - push string "sin" 52 - call method 26 - trace

0x60 - bitwise AND

<int a> <int b> 0x60 ==> <a & b>

0x61 - bitwise OR

<int a> <int b> 0x61 ==> <a | b>

0x62 - bitwise XOR

<int a> <int b> 0x62 ==> <a ^ b>

0x3f - modulo

<int a> <int b> 0x3f ==> <a % b>

0x47 - add

<num a> <num b> 0x3f ==> <a + b>

Note: the old addition op 0x0a doesn't seem to be used in Flash 5

Note note: actually, this op does string concat, too.

0x48 - less than

<num a> <num b> 0x48 ==> <a < b>

Note: the old less than op 0x0f doesn't seem to be used in Flash 5

0x49 - equals

<num a> <num b> 0x49 ==> <a == b>

Note: the old equals op doesn't seem to be used in Flash 5

0x50 - increment?

<num a> 0x50 ==> <a+1>

0x4c - make boolean?

<num a> 0x4c ==> <boolean(a)>

0x44 - typeof?

<data a> 0x44 ==> <typeof(a)>

0x46 - dumps array keys onto stack

<string arrayname> 0x46 ==> <array keys>

0x87 - copy top of stack into "register"

<data> 0x87 <short length=1> <byte n> ==> <data>

copies the data from the stack and puts it into "register" (see push 0x96 op, type 4) number n.

0x3a - delete

<string varname> 0x3a ==> <boolean result>

Attempts to delete the named variable, returns true if successful else false.

ex: delete(a)

96 03 00 00 _a 00  - push string "a"
3a                 - delete

0x40 - instantiate object; i.e., "new"

[data args] <int numargs> <string classname> 0x40 ==> <class instance>

0x4e - get member

<object obj> <member> 0x4e ==> <obj.member>

member can be string or number

0x4f - set member

<object obj> <member> <value> 0x4f

member can be either a string or a number.

Ex: obj['idx'] = 3

96 05 00 00 _o _b _j 00     - push string "obj"
1c                          - get value of obj
96 0b 00 00 _i _d _x 00     - push string "idx"
         07 03 00 00 00 00  - and number 3
4f                          - set member

0x94 - "with"

<object obj> 0x94 <short length> <short size>

following size bytes are the "with" block- i.e., references to variables and functions are first looked for inside the "with" object. ??

0x63 - shift left

<num a> <num b> 0x63 ==> <a<<b>

0x64 - shift right

<num a> <num b> 0x64 ==> <a>>b>

0x65 - shift right w/ rotate (?)

<num a> <num b> 0x65 ==> <a>>>b>

0x41 - declare local variable w/out value

<string name> 0x41

Ex: var i;

96 03 00 00 _i 00   - push string "i"
41                  - declare local var "i"

0x3c - declare local variable w/ value

<string name> <value> 0x3c

Ex: var i=a

96 06 00 00 _i 00   - push string "i"
         00 _a 00   - and string "a"
1c                  - get value of "a"
3c                  - set local var "i" to value of "a"

Other Notes

The logical && and || operators do proper short-circuiting; the second argument won't be evaluated if the first is sufficient to determine the truth/falsity of the statement. Example:

if(func1() || func2())
  do_something();

compiles to (pseudocode):

if(func1())
  goto a;
else
  goto end;

if(!func2())
  goto end;

a: do_something();

end:

or, in plain English: if func1() evaluates true, func2() is never called.

Also, the bitwise NOT operator ~ doesn't have an opcode, but compiles to an XOR with 0xffffffff.


Movie clip actions

(addendum to placeobject2 format)

if placeobject2 flag 1<<7 (msb) is set, the following data is added to the end of the placeobject2 block:

<short ???>
<short flags> - the logical OR of the flags from the following handler blocks

any number of:
<short flags> - indicating which events (described below) this clip responds to
<int length>
<action bytecode> - handler code for this event
<short 0 (end)>

event flags:

flagmeaning
0x01on load
0x02enter frame
0x04unload
0x08mouse move
0x10mouse down
0x20mouse up
0x40key down
0x80key up
0x100data


Get/set-properties

numberproperty
6_alpha
4_currentframe
14_droptarget
17_focusrect
12_framesloaded
9_height
16_highquality
13_name
19_quality
10_rotation
18_soundbuftime
11_target
5_totalframes
15_url
7_visible
8_width
0_x
20_xmouse
2_xscale
1_y
21_ymouse
3_yscale