使用jvm指令解析局部变量的加减乘除
2020-03-17 本文已影响0人
suc浮生
基础指令说明
- 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
}
来源:苏克分享公众号