美文网首页痴于技术
使用jvm指令解析局部变量的加减乘除

使用jvm指令解析局部变量的加减乘除

作者: suc浮生 | 来源:发表于2020-03-17 14:06 被阅读0次

    基础指令说明

    • iconst类指令说明 (部分志指令):
    该系列命令主要负责把简单的数值类型送到栈顶。该系列命令不带参数。注意只把简单的数值类型送到栈顶时,才使用如下的命令。比如对应int型才该方式只能把-1,0,1,2,3,4,5(分别采用iconst_m1,iconst_0, iconst_1, iconst_2, iconst_3,iconst_4, iconst_5)送到栈顶。对于int型,其他的数值请使用push系列命令(比如bipush)
    
     | 指令码  | 助记符 |      说明         |
     | ------------- | ------------- |------------- |
     | 0x02  | iconst_m1  | 将int型(-1)推送至栈顶  |
     | 0x03  | iconst_0  | 将int型(0)推送至栈顶  |
     | 0x04  | iconst_1  | 将int型(1)推送至栈顶  |
     | 0x05  | iconst_2  | 将int型(2)推送至栈顶  |
     | 0x06  | iconst_3  | 将int型(3)推送至栈顶  |
     | 0x07  | iconst_4  | 将int型(4)推送至栈顶  |
    
    • store系列
    该系列命令负责把栈顶的值存入本地变量。这里的本地变量不仅可以是数值类型,还可以是引用类型。如果是把栈顶的值存入到前四个本地变量的话,采用的是istore_0,istore_1,istore_2,istore_3(它们分别表示第0,1,2,3个本地整形变量)这种不到参数的简化命令形式。如果是把栈顶的值存入到第四个以上本地变量的话,将使用istore命令这种形式,在它后面给一参数,以表示是把栈顶的值存入到第几个(从0开始)本地变量中。对本地变量所进行的编号,是对所有类型的本地变量进行的(并不按照类型分类)。对于非静态函数,第一变量是this,它是只读的.还有函数传入参数也算本地变量,在进行编号时,它是先于函数体的本地变量的。
    
    • push系列
    该系列命令负责把一个整形数字(长度比较小)送到到栈顶。该系列命令有一个参数,用于指定要送到栈顶的数字。注意该系列命令只能操作一定范围内的整形数值,超出该范围的使用将使用ldc命令系列。
    
    • load系列(部分志指令)
     | 指令码  | 助记符 |      说明         |
     | ------------- | ------------- |------------- |
    |0x15 |iload |将指定的int型本地变量推送至栈顶|
    |0x16 |lload |将指定的long型本地变量推送至栈顶|
    |0x17 |fload |将指定的float型本地变量推送至栈顶|
    |0x18 |dload |将指定的double型本地变量推送至栈顶|
    |0x19 |aload |将指定的引用类型本地变量推送至栈顶|
    |0x1a |iload_0 |将第一个int型本地变量推送至栈顶|
    |0x1b |iload_1 |将第二个int型本地变量推送至栈顶|
    |0x1c |iload_2 |将第三个int型本地变量推送至栈顶|
    |0x1d |iload_3 |将第四个int型本地变量推送至栈顶|
    | ------------- | ------------- |------------- |
    |0x2e |iaload |将int型数组指定索引的值推送至栈顶|
    |0x2f |laload |将long型数组指定索引的值推送至栈顶|
    |0x30 |faload |将float型数组指定索引的值推送至栈顶|
    |0x31 |daload |将double型数组指定索引的值推送至栈顶|
    
    • 栈顶元素数学操作及移位操作系列(部分志指令)
    | 指令码  | 助记符 |      说明         |
     | ------------- | ------------- |------------- |
     |0x5f  |swap  |将栈最顶端的两个数值互换(数值不能是long或
     double类型的)
     |0x60  |iadd  |将栈顶两int型数值相加并将结果压入栈顶
     |0x61  |ladd  |将栈顶两long型数值相加并将结果压入栈顶
     |0x62  |fadd  |将栈顶两float型数值相加并将结果压入栈顶
     |0x63  |dadd  |将栈顶两double型数值相加并将结果压入栈顶
     |0x64  |isub  |将栈顶两int型数值相减并将结果压入栈顶
     |0x65  |lsub  |将栈顶两long型数值相减并将结果压入栈顶
     |0x66  |fsub  |将栈顶两float型数值相减并将结果压入栈顶
     |0x67  |dsub  |将栈顶两double型数值相减并将结果压入栈顶
    

    基础类

    class Test{
      public static void main(String args[]){
       int a=1;
       int b=2;
       int c=(a+b)*101;
       int d = c-20;
       System.out.print(d);
      }
    }
    
    • 反编译
    javac Test.java
    javap -c Test.class > Test.txt # 得到反编译后的代码
    
    • 得到编译后的结果:
    Compiled from "Test.java"
    class Test {
      Test();
        Code:
           0: aload_0  第一变量是this,
           1: invokespecial #1   调用超类构造方法,实例初始化方法,私
    有方法                // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: iconst_1    第一个变量压入栈顶
           1: istore_1    将栈顶值存入第一个本地变量
           2: iconst_2    第二个变量压入栈顶
           3: istore_2    将栈顶值存入第二个本地变量
           4: iload_1     第一个本地变量送到栈顶
           5: iload_2     第二个本地变量送到栈顶
           6: iadd        add顾名思义 加法运算 (a+b)
           7: bipush        101  将101送到栈顶
           9: imul       将栈顶两int型数值相乘并将结果压入栈顶 即(a+b)* 101
          10: istore_3    将第三个变量存入本地变量 ---c的值
          11: iload_3     第三个本地变量入栈顶
          12: bipush        20  将20压入栈顶
          14: isub            将栈顶两int型数值相减并将结果压入栈顶  减法运算
          15: istore        4   将栈顶int型数值存入指定本地变量 即d的值
          17: getstatic     #2      获取指定类的静态域,并将其值压入栈顶             // Field java/lang/System.out:Ljava/io/PrintStream;
          20: iload         4   将指定的int型本地变量推送至栈顶 即d的值
          22: invokevirtual #3         调用实例方法         // Method java/io/PrintStream.print:(I)V
          25: return  从当前方法返回void
    } 
    

    来源:苏克分享公众号

    相关文章

      网友评论

        本文标题:使用jvm指令解析局部变量的加减乘除

        本文链接:https://www.haomeiwen.com/subject/elrtyhtx.html