Java字节码跟真正汇编的比较

2020-05-28 22:36:18 浏览数 (1)

我们来看一下这样一段逻辑(Java实现)

代码语言:javascript复制
public void print(int i,int j) {
    int f;
    if (i == j) {
        f = i   j;
    }else {
        f = i - j;
    }
}

编译后的字节码

代码语言:javascript复制
 public void print(int, int);
    descriptor: (II)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=3
         0: iload_1                      //将局部变量表第一个整型变量i入栈
         1: iload_2                      //将局部变量表第二个整型变量j入栈
         2: if_icmpne     12             //将操作数栈的两个整型变量弹出并进行相等比较,如果不相等则跳到位置为12的地方
         5: iload_1                      //如果相等,将局部变量表第一个整型变量i入栈
         6: iload_2                      //如果相等,将局部变量表第二个整型变量j入栈
         7: iadd                         //将操作数栈的两个整型变量弹出,并相加后将结果入栈
         8: istore_3                     //将相加的结果从栈顶弹出并赋值给局部变量表的第三个整型变量f
         9: goto          16             //跳转到位置16
        12: iload_1                      //如果不相等,将局部变量表第一个整型变量i入栈
        13: iload_2                      //如果不相等,将局部变量表第二个整型变量j入栈
        14: isub                         //将操作数栈的两个整型变量弹出,并相减后将结果入栈
        15: istore_3                     //将相减的结果从栈顶弹出并赋值给局部变量表的第三个整型变量f
        16: return
      LineNumberTable:
        line 7: 0
        line 8: 5
        line 10: 12
        line 12: 16
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            9       3     3     f   I
            0      17     0  this   Lcom/guanjian/calculate/test/Calc;
            0      17     1     i   I
            0      17     2     j   I
           16       1     3     f   I

其汇编语言如下

代码语言:javascript复制
bne $r3,$r4,ELSE         //判断r3寄存器与r4寄存器是否相等,如果不等跳转到ELSR标记处
add $r5,$r3,$r4          //如果相等,则将r3寄存器和r4寄存器相加将结果放入r5寄存器
j EXIT                   //跳转到EXIT标记处
ELSE:
sub $r5,$r3,$r4          //如果不相等,则将r3寄存器和r4寄存器相减将结果放入r5寄存器
EXIT:

通过比较,其实也能看出来,Java字节码的入栈操作其实也就是放入寄存器中,出栈也就是清理寄存器。

Java代码

代码语言:javascript复制
public void print() {
    int sum = 0;
    for (int i = 0;i < 100;i  ) {
        sum  = i;
    }
}

编译后的字节码

代码语言:javascript复制
public void print();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: iconst_0                 //入栈整数0
         1: istore_1                 //将栈顶0弹出并赋值给局部变量表第一个整型变量sum
         2: iconst_0                 //入栈整数0
         3: istore_2                 //将栈顶0弹出并赋值给局部变量表第二个整型变量i
         4: iload_2                  //将局部变量表第二个整型变量i入栈
         5: bipush        100        //入栈100
         7: if_icmpge     20         //将操作数栈的两个值弹出并判断i是否小于100,如果不小于100跳转到位置20
        10: iload_1                  //将局部变量表第一个整型变量sum入栈
        11: iload_2                  //将局部变量表第二个整型变量i入栈
        12: iadd                     //将操作数栈的两个整型变量弹出并相加后将结果入栈
        13: istore_1                 //将栈顶的结果弹出并赋值给局部变量表第一个整型变量sum
        14: iinc          2, 1       //将局部变量表的第二个整型变量i自增1
        17: goto          4          //跳转到位置4
        20: return
      LineNumberTable:
        line 6: 0
        line 7: 2
        line 8: 10
        line 7: 14
        line 10: 20
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            4      16     2     i   I
            0      21     0  this   Lcom/guanjian/calculate/test/Calc;
            2      19     1   sum   I

其汇编语言为

代码语言:javascript复制
addi $s3,$zero,0         //0加上一个常数寄存器zero(里面的数就是0)存入s3寄存器int sum = 0;
addi $s4,$zero,0         //0加上一个常数寄存器zero(里面的数就是0)存入s4寄存器int i = 0
addi $s5,$zero,100       //100加上一个常数寄存器zero(里面的数就是0)存入s5寄存器100
LOOP:
beq $s4,$s5,EXIT         //比较s4寄存器的值是否小于S5寄存器的值,如果如果结果为假跳转到EXIT标记i < 100
add $s3,$s4,$s3          //将s4寄存器和s3寄存器的值相加存入s3寄存器sum  = i;
addi $s4,$s4,1           //将s4寄存器的值加1存入s4寄存器i  
j LOOP                   //跳转到LOOP标记
EXIT:

0 人点赞