format: if<cond> branchByte1 branchByte2

从栈中弹出一个值,和0进行比较,根据指令的不同,有不同的比较方法得出一个值,如果为假,则顺序执行后面的指令。那为真的呢?:

branchByte1 branchByte2 都是 0x00 - 0xFF 之间的一个 unsigned 值,可以用他俩算出来offset作为true branch的入口,公式为:

(branchbyte1 << 8) | branchbyte2

例子:

116: bipush        1
118: ifeq          132
121: getstatic     #12      // Field java/lang/System.out:Ljava/io/PrintStream;
124: bipush        1
126: invokevirtual #28      // Method java/io/PrintStream.println:(Z)V
129: goto          140
132: getstatic     #12      // Field java/lang/System.out:Ljava/io/PrintStream;
135: bipush        0

行中ifeq 132的二进制表示为99 00 0E。99代表该指令,00和0E代表两个操作数。

计算偏移量:(0x00 << 8) | 0x0E 得 14

就是说ifeq开头为118,加上14个偏移量为132,所以132是 true branch 的入口。

问题:

一、为什么需要两个操作数呢?

(一)通过观察 java 编译后的 class 文件,我发现 branchByte1 都是 0x00,完全没有必要为这样一个固定的值设计一个位置呀。

自答:如果 true branch 非常长(true branch 里的指令长度超过了255,那么 branchByte1 是会增长的。

(二)(branchbyte1 << 8) | branchbyte2的结果还是8位,难道不可以用一个 byte 来表示,为什么需要用两个 byte 计算后得到结果呢?

自答:如上所述,需要两个来处理 condition 很长的情况。