Here is an example of a high level language block of code, its IJVM equivalent, and the corresponding java Byte Code. I have added a column for the byte offset of each Java Byte Code hex instruction. The byte offset is just the count of the bytes, starting at 0.
The big question is: how are the 16-bit offsets for the branch instructions calculated.
The big answer is: count the number of bytes to the destination.
The first branch is in instruction 7 in the IJVM code, and at offset 11 in
the hex byte code. The destination of the jump is label L1, which is located
in instruction 13 in the IJVM, and at offset 24 in the hex byte code. Subtract
the offset of the start of the instruction from the offset of the label to
get the displacement that is placed into the jump instruction.
24 - 11 = 13 = 0x0000D
This is the reason why the conditional branch in the byte code is 0x9F
0x00 0x0D
. The op code is 9F and the displacement is 0x000D.
The second branch instruction is the GOTO in instruction 12 of the IJVM,
and offset 21 in the hex byte code. The destination is label L2, which is
located in instruction 15 in the IJVM, and offset 28 in the hex byte
code.
28 - 21 = 7 = 0x0007
This is the reason why the branch in the byte code is 0xA7 0x00
0x07
. The op code is A7and the displacement is 0x0007.
As one final example, suppose there was a branch to a higher location. For
example, suppose that instruction 15 in the IJVM were GOTO L1. The offset
of the GOTO would be 28, and the offset of L1 would be 24. Subtract the offset
of the start of the instruction from the offset of the label
24 - 28 = -4 = 0xFFFC
Such a GOTO would have the format 0xA7 0xFF 0xFC
. To represent
a negative displacement, use the 2's complement of the number.