| 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:
number type # of bytes 00 Null-terminated string strlen+1 02 NULL (?) 0 03 ??? 0 04 "register" (see below) 1 05 boolean (1=true, 0=false) 1 06 double 8 07 int 4 08 dictionary 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<short 0 (end)>
<int length>
<action bytecode> - handler code for this event
event flags:
flag meaning 0x01 on load 0x02 enter frame 0x04 unload 0x08 mouse move 0x10 mouse down 0x20 mouse up 0x40 key down 0x80 key up 0x100 data
| Get/set-properties |
number property 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