An Oolong instruction corresponds to a single bytecode instruction in the class file. Each instruction is written as a single mnemonic. Depending on the instruction, the mnemonic may be followed by one or more arguments to the instruction. The following table summarizes all of the available Oolong instructions. The rest of the section provides notes on the arguments. Mnemonic | Arguments | Description | aaload | | Push array element | aastore | | Store a in array element | aconst_null | | Push null reference | aload | n | Push local variable n | aload_0 | | Push local variable 0 | aload_1 | | Push local variable 1 | aload_2 | | Push local variable 2 | aload_3 | | Push local variable 3 | anewarray | class | Create array of class, length a | areturn | | Return reference from method | arraylength | | Length of array a | astore | n | Store a in local variable n | astore_0 | | Store a in local variable 0 | astore_1 | | Store a in local variable 1 | astore_2 | | Store a in local variable 2 | astore_3 | | Store a in local variable 3 | athrow | | Throw exception | baload | | Push array element | bastore | | Store a in array element | bipush | n | Push int between 128 and 127 | caload | | Push array element | castore | | Store a in array element | checkcast | class | Throw exception if a is not class | d2f | | Convert double to float | d2i | | Convert double to int | d2l | | Convert double to long | dadd | | Add doubles (ab+cd) | daload | | Push array element | dastore | | Store a in array element | dcmpg | | Compare doubles | dcmpl | | Compare doubles | dconst_0 | | Push 0 (double) | dconst_1 | | Push 1 (double) | ddiv | | Divide doubles (ab/cd) | dload | n | Push local variable n | dload_0 | | Push local variable 0 | dload_1 | | Push local variable 1 | dload_2 | | Push local variable 2 | dload_3 | | Push local variable 3 | dmul | | Multiply doubles (ab*cd) | dneg | | Negate double (-ab) | drem | | Remainder doubles (ab%cd) | dreturn | | Return double from method | dstore | n | Store ab in local variable n | dstore_0 | | Store a in local variable 0 | dstore_1 | | Store a in local variable 1 | dstore_2 | | Store a in local variable 2 | dstore_3 | | Store a in local variable 3 | dsub | | Subtract doubles (ab-cd) | dup | | Duplicate a | dup_x1 | | Duplicate b | dup_x2 | | Duplicate c | dup2 | | Duplicate ab | dup2_x1 | | Duplicate bc | dup2_x2 | | Duplicate cd | f2d | | Convert float to double | f2i | | Convert float to int | f2l | | Convert float to long | fadd | | Add floats (a+b) | faload | | Push array element | fastore | | Store a in array element | fcmpg | | Compare floats | fcmpl | | Compare floats | fconst_0 | | Push 0 (float) | fconst_1 | | Push 1 (float) | fconst_2 | | Push 2 (float) | fdiv | | Divide floats (a/b) | fload | n | Push local variable n | fload_0 | | Push local variable 0 | fload_1 | | Push local variable 1 | fload_2 | | Push local variable 2 | fload_3 | | Push local variable 3 | fmul | | Multiply floats (a*b) | fneg | | Negate float (-a) | frem | | Remainder floats (a%b) | freturn | | Return float from method | fstore | n | Store a in local variable n | fstore_0 | | Store a in local variable 0 | fstore_1 | | Store a in local variable 1 | fstore_2 | | Store a in local variable 2 | fstore_3 | | Store a in local variable 3 | fsub | | Subtract floats (a-b) | getfield | class/field desc | Push object field | getstatic | class/field desc | Push static field | goto | label | Branch always | goto_w | label | Branch always to label | i2b | | Convert int to byte | i2c | | Convert int to char | i2d | | Convert int to double | i2f | | Convert int to float | i2l | | Convert int to long | i2s | | Convert int to short | iadd | | Add ints (a+b) | iaload | | Push array element | iand | | Bitwise and ints (a & b) | iastore | | Store a into array element | iconst_0 | | Push 0 (int) | iconst_1 | | Push 1 (int) | iconst_2 | | Push 2 (int) | iconst_3 | | Push 3 (int) | iconst_4 | | Push 4 (int) | iconst_5 | | Push 5 (int) | iconst_m1 | | Push 1(int) | idiv | | Divide ints (a/b) | if_acmpeq | label | Branch if a == b | if_acmpne | label | Branch if a != b | if_icmpeq | label | Branch if a > b | if_icmpge | label | Branch if a >= b | if_icmpgt | label | Branch if a > b | if_icmple | label | Branch if a <= b | if_icmplt | label | Branch if a < b | if_icmpne | label | Branch if a != b | ifeq | label | Branch if a == 0 | ifge | label | Branch if a >= 0 | ifgt | label | Branch if a > 0 | ifle | label | Branch if a <= 0 | iflt | label | Branch if a < 0 | ifne | label | Branch if a != 0 | ifnonnull | label | Branch if a is not null | ifnull | label | Branch if a is null | iinc | n increment | Increment local variable | iload | n | Push local variable n | iload_0 | | Push local variable 0 | iload_1 | | Push local variable 1 | iload_2 | | Push local variable 2 | iload_3 | | Push local variable 3 | imul | | Multiply ints (a*b) | ineg | | Negate int (-a) | instanceof | class | Push 1 if a is class, 0 otherwise | invokeinterface | class/method desc n | Invoke method through interface with n argument words | invokespecial | class/method desc | Invoke method directly | invokestatic | class/method desc | Invoke static method | invokevirtual | class/method desc | Invoke method virtually | ior | | Bitwise or ints (a | b) | irem | | Remainder ints (a%b) | ireturn | | Return int from method | ishl | | Shift int left (a << b) | ishr | | Shift int right (a >> c) | istore | n | Store a in local variable n | istore_0 | | Store a in local variable 0 | istore_1 | | Store a in local variable 1 | istore_2 | | Store a in local variable 2 | istore_3 | | Store a in local variable 3 | isub | | Subtract ints (a-b) | iushr | | Unsigned shift int right (a >>> c) | ixor | | Boolean xor ints (a ^ b) | jsr | label | Branch to label; push return location | jsr_w | label | Jump to label | l2d | | Convert long to double | l2f | | Convert long to float | l2i | | Convert long to int | ladd | | Add longs (ab+cd) | laload | | Push array element | land | | Boolean and longs (ab & cd) | lastore | | Store a in array element | lcmp | | Compare longs | lconst_0 | | Push 0 (long) | lconst_1 | | Push 1 (long) ldc | ldc_w | x | Push x (a constant int, float, or String) | ldc2_w | x | Push x (a constant long or double) | ldiv | | Divide longs (ab/cd) | lload | n | Push local variable n | lload_0 | | Push local variable 0 | lload_1 | | Push local variable 1 | lload_2 | | Push local variable 2 | lload_3 | | Push local variable 3 | lmul | | Multiply longs (ab*cd) | lneg | | Negate long (-ab) | lookupswitch | tag1: label1 tag2: label2 … default: labeln | Branch to label1 on tag1, label2 on tag2, …, labeln otherwise | lor | | Boolean or longs (ab | cd) | lrem | | Remainder longs (ab%cd) | lreturn | | Return long from method | lshl | | Shift long left (bc << 9) | lshr | | Shift long right (bc >> 9) | lstore | n | Store ab in local variable n | lstore_0 | | Store a in local variable 0 | lstore_1 | | Store a in local variable 1 | lstore_2 | | Store a in local variable 2 | lstore_3 | | Store a in local variable 3 | lsub | | Subtract longs (ab-cd) | lushr | | Unsigned shift long right (bc >>> a) | lxor | | Boolean xor longs (ab ^ cd) | monitorenter | | Gain control of monitor of a | monitorexit | | Release monitor of a | multianewarray | class n | Create multidimensional array with first n dimensions initialized to lengths a,b,c… | new | class | Create new object of class | newarray | type | Create array of type, length a | nop | | Do nothing | pop | | Remove a | pop2 | | Remove ab | putfield | class/field desc | Store a in object field | putstatic | class/field desc | Store a in static field | ret | n | Branch to location in variable n | return | | Return from method | saload | | Push array element | sastore | | Store a in array element | sipush | n | Push int between 32,768 and 32767 | swap | | Swap a and b | tableswitch | n label1 label2 … default: labeln | Branch to label1 on n, label2 on n+1, …, labeln otherwise | wide | instruction arguments | Like instruction, except using wider range of values | B.5.1 Instructions with No Arguments Most instructions require no arguments; the instruction is written with just the mnemonic. For example: aload_0 ; Push the reference in variable 0 freturn ; Return a float value ladd ; Add two longs monitorenter ; Acquire the monitor B.5.2 Integers Integer values are specified as in Java. They may be either numerical constants or single-character literals. For example, bipush 65 ; Push the int 65 bipush 0x41 ; Ditto bipush 'A' ; Same B.5.3 Labels A label indicates a particular instruction. When an instruction has a label as its argument, the destination is the next instruction after the label. For example, goto label ; Jump to the nop instruction ;; This code is skipped label: nop aload_0 arraylength ifeq label ; Jump again to the nop instruction The instruction identified by label is the nop instruction. B.5.4 Classes Some instructions, such as new, require classes as arguments. These arguments are written as the fully qualified class name, using slashes (/) as the separators between package components. For example, new java/lang/String ; Create a String B.5.5 Fields and Methods The general format of a field access or method invocation instruction is mnemonic classname/entity desc where classname is the name of the class, entity is the name of the field or method, and descriptor is the field or method descriptor. For example, to access a method: invokevirtual java/io/PrintStream/println (Ljava/lang/String;)V In this case, classname is java/io/PrintStream, entity is println, and desc is (Ljava/lang/String;)V. For a field: getstatic java/lang/Math/PI D Here, classname is java/lang/Math, entity is PI, and desc is D. B.5.6 invokeinterface In the case of the invokeinterface instruction, there is an additional argument: the number of stack elements used in the call, including the object itself. This information is redundant, since it can be determined from the descriptor, but it is required by the JVM. For example, invokeinterface Interface/method (JJ[Ljava/lang/String;)D 6 invokes a method through the interface called Interface, which requires three arguments, two longs and an array of Strings. The number in this case is 6: one for the Interface object, two for each of the longs, and one more for the String array. The double returned is not included. B.5.7 multianewarray The multianewarray instruction is used to create a multidimensional array, with the first n dimensions initialized. The first argument of a multianewarray call is the type descriptor of the type that is to be created. It must be an array type; that is, the descriptor must begin with one or more left brackets ([). The second element describes how much of the array should be initialized. For example, bipush 30 bipush 90 sipush 1000 multianewarray [[[[[I 3 creates a five-dimensional array of ints. The first three dimensions are initialized to 30, 90, and 1000 elements. This is equivalent to the Java expression new int[30][90][1000][][] which is an array 30 elements long. Each element of the array is 90 elements long. Each element of that array is 1000 elements long. Each of those 30 x 90 x 1000 = 2,700,000 elements is initially null, but it can hold a two-dimensional array of ints. B.5.8 ldc, ldc_w, and ldc2_w These three instructions are used to push a constant value onto the stack. These values are represented as in Java. In Oolong, ldc and ldc_w generate identical code. The JVM distinguishes between these two instructions depending on which element of the constant pool holds the value of the constant. If the value is 256 or less, the ldc is used; otherwise, ldc_w is used. Since the Oolong assembler manages the constant pool, it decides whether to use an ldc or ldc_w opcode. The ldc2_w instruction is used for double and long values, that is, values that take up two stack entries. For example, ldc "Some string" ; Push a String ldc 3.14 ; Push a floating-point constant ldc_w 3.14 ; The same ldc2_w 3.1415925358979323D ; Push a double constant B.5.9 newarray The newarray instruction is used to create a single-dimensional array of one of the base types. The argument specifies the basic type to create. It may be specified either as the Java type name (int), the Java type descriptor (I), or the bytecode internal number for the type (10). This table summarizes the possible values; all values in the same row are equivalent. Java name | Descriptor | Value | boolean | Z | 4 | char | C | 5 | float | F | 6 | double | D | 7 | byte | B | 8 | short | S | 9 | int | I | 10 | long | J | 11 | For example, sipush 10 newarray J ; Create a ten-element array of longs B.5.10 tableswitch The tableswitch instruction takes a base value, specified as an integer, followed by a set of labels. If the value is equal to the base value, control transfers to the first label. If it is one greater than the base, it goes to the second label, and so on. The default case is required; it specifies where to go if the value is lower than the base or if it is greater than the number of provided labels allowed. For example, tableswitch 'A' caseA caseB caseC default: invalidLetter caseA: ; Handle a letter A caseB: ; Handle a letter B caseC: ; Handle a letter C invalidLetter: ; Throw an exception B.5.11 lookupswitch The lookupswitch instruction is much like tableswitch (section B.5.10), except that instead of a single value, explicit combinations of cases and labels are provided. The cases are int constants. As with tableswitch, the default case is required. For example, lookupswitch 'A': caseA 'B': caseB 'C': caseC default: invalidLetter This could also be written as lookupswitch 65: caseA 66: caseB 67: caseC default: invalidLetter or as lookupswitch 0x41: caseA 0x42: caseB 0x43: caseC default: invalidLetter |