Logic and Integer Arithmetic
Java's Bytecodes for Logical and Arithmetic Operations
by Bill Venners
First Published in JavaWorld, November 1996

<<  Page 2 of 3  >>

Arithmetic opcodes
Integer addition can be performed on ints and longs. Bytes, shorts, and chars are automatically converted to int before they take part in an addition. The following table shows the opcodes that pop the top two values on the stack, add them, and push the result. The type of the values is indicated by the opcode itself, and the result always has the same type as the numbers being added. No exceptions are thrown for any of these opcodes. Overflow is just ignored.

Opcode Operand(s) Description iadd (none) pops two ints, adds them, and pushes the int result ladd (none) pops two longs, adds them, and pushes the long result

The next table shows the exception to the rule that arithmetic opcodes take their operands from the stack. The iinc opcode performs an addition on a local variable of type int. The local variable is indicated by the first byte that follows the iinc instruction in the bytecode stream. The amount to add to the local variable is taken from the second byte following the iinc instruction. The second byte is interpreted as a byte type, an eight-bit signed two's-complement number. The local variable and byte are added, and the result is written back to the local variable. This opcode can be used to change a local variable value by any number between and including -128 through 127. This opcode makes for more efficient incrementing and decrementing of variables that are used to control execution of loops, such as for or while. No exceptions are thrown.

Opcode Operand(s) Description iinc vindex, const adds const to an int at local variable position vindex

Integer subtraction is performed on ints and longs via the following opcodes. Each opcode causes the top two values of the appropriate type to be popped off the stack. The topmost value is subtracted from the value just beneath the topmost value. The result is pushed back onto the stack. No exceptions are thrown by these opcodes.

Opcode Operand(s) Description isub (none) pops two ints, subtracts them, and pushes the int result lsub (none) pops two longs, subtracts them, and pushes the long result

Integer multiplication of ints and longs is accomplished via the following opcodes. Each opcode causes two values of the same type to be popped off the stack and multiplied. The result, of the same type as the numbers being multiplied, is pushed back onto the stack. No exceptions are thrown.

Opcode Operand(s) Description imul (none) pops two ints, multiplies them, and pushes the int result lmul (none) pops two longs, multiplies them, and pushes the long result

The opcodes that perform division on ints and longs are shown in the next table. The division opcodes cause the top two values of the appropriate type to be popped off the stack. The topmost value is divided by the value just beneath the topmost value. The result is pushed onto the stack. Integer division yields a result that is truncated down to the nearest integer value between it and zero. Integer division by zero throws a "/ by 0" ArithmeticException.

Opcode Operand(s) Description idiv (none) pops two ints, divides them, and pushes the int result ldiv (none) pops two longs, divides them, and pushes the long result

The remainder operation is accomplished via the following opcodes on ints and longs. The following opcodes cause the top two values to be popped from the stack. The topmost value is divided by the value just beneath it, and the remainder of that division is pushed back onto the stack. As with the division opcodes, integer remainder by zero throws a "/ by 0" ArithmeticException.

Opcode Operand(s) Description irem (none) pops two ints, divides them, and pushes the int remainder lrem (none) pops two longs, divides them, and pushes the long remainder

The following opcodes perform arithmetic negation on ints and longs. The negation opcodes pop the top value from the stack, negate it, and push the result.

Opcode Operand(s) Description ineg (none) pops an int, negates it, and pushes the result lneg (none) pops a long, negates it, and pushes the result

Logical operands
The JVM's logic capabilities operate on ints and longs. These operations treat ints and longs not as signed two's-complement numbers, necessarily, but more as generic bit patterns. Integer shifting is accomplished via the ishl, ishr, and iushr opcodes. Java's << operator is implemented by ishl. The >> operator is implemented by ishr, and the >>> operator is implemented by iushl. The difference between ishr and iushr is that only ishr does sign extension. The following table shows the instructions that shift ints left and right.

Opcode Operand(s) Description ishl (none) shifts int left ishr (none) arithmetic shifts int right iushr (none) logical shifts int right

The next table shows the instructions that shift longs left and right.

Opcode Operand(s) Description lshl (none) shifts long left lshr (none) arithmetic shifts long right lushr (none) logical shifts long right

The following opcodes perform bitwise logical operations on ints. The opcodes implement Java's &, |, and ^ operators.

Opcode Operand(s) Description iand (none) boolean ands two ints ior (none) boolean ors two ints ixor (none) boolean xors two ints

The next table shows the opcodes that perform bitwise logical operations on longs.

Opcode Operand(s) Description land (none) boolean ands two longs lor (none) boolean ors two longs lxor (none) boolean xors two longs

<<  Page 2 of 3  >>