多读书多实践,勤思考善领悟

Java逆向基础之一.常量入栈指令

本文于2004天之前发表,文中内容可能已经过时。

常量入栈指令

常量入栈指令有iconst、bipush、sipush、ldc、ldc2_w分别对应不同的使用场景

以下两个表简单总结了使用场景

八大基本类型场景表

常量类型 常量范围 指令
整型int -1~5 iconst_0~ iconst_5 iconst_m1
-128~127 bipush
-32768~32767 sipush
-2147483648~2147483647 #2 = Integer 12345678 0: ldc #2 // int 12345678
布尔型boolean true iconst_1
false iconst_0
短整型short -1~5 iconst_0~ iconst_5 iconst_m1
-128~127 bipush
-32768~32767 sipush
字符型char \u0000~\u0005 iconst_0~ iconst_5
\u0000~\u00FF bipush
\u0000~\uFFFF sipush
字节型byte -1~5 iconst_0~ iconst_5 iconst_m1
-128~127 bipush
长整型long -2\^63~2\^63-1 #2 = Long 1234567890123456789l ldc2_w #2 // long 1234567890123456789l
浮点型double 8字节 #2 = Double 123.456d ldc2_w #2 // double 123.456d
浮点型float 4字节 #2 = Float 123.456f ldc #2 // float 123.456f

指令场景表

指令 使用场景
iconst int,short,byte,int(char a)数值在-1~5之间,boolean类型,注意不包括long
bipush int,short,byte,int(char a)数值在-128~127之间,注意不包括long,范围内的值在iconst之内的优先用iconst
sipush int,short,int(char a)数值在-32768~32767之间,boolean类型,注意不包括long,范围内的值在bipush之内的优先用bipush
ldc int的数值-2147483648~2147483647之间(范围内的值在sipush之内的优先用sipush),float类型
ldc2_w long类型,double类型

以下是简单的例子

整型常量0的例子iconst

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ret

{

public static int main(String[] args)

{

return 0;

}

}

编译

1
javac ret.java

Java标准反编译

1
javap -c -verbose ret.class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...

major version: 52

...

public static int main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)I

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=1, locals=1, args_size=1

0: iconst_0

1: ireturn

LineNumberTable:

line 5: 0
  • 注意其中的0: iconst_0即可

整型常量123的例子bipush

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ret

{

public static int main(String[] args)

{

return 123;

}

}

反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...

major version: 52

...

public static int main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)I

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=1, locals=1, args_size=1

0: bipush        123

2: ireturn

LineNumberTable:

line 5: 0
  • 注意其中的0: bipush 123

整型常量1234的例子sipush

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ret

{

public static int main(String[] args)

{

return 1234;

}

}

反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...

major version: 52

...

public static int main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)I

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=1, locals=1, args_size=1

0: sipush        1234

3: ireturn

LineNumberTable:

line 5: 0
  • 注意其中的 0: sipush 1234

整型常量12345678的例子ldc

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ret

{

public static int main(String[] args)

{

return 12345678;

}

}

反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...

major version: 52

...

\#2 = Integer            12345678

...

public static int main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)I

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=1, locals=1, args_size=1

0: ldc           \#2                  // int 12345678

2: ireturn

LineNumberTable:

line 50

布尔型true例子iconst

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ret

{

public static boolean main(String[] args)

{

return true;

}

}

反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...

major version: 52

...

public static boolean main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)Z

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=1, locals=1, args_size=1

0: iconst_1

1: ireturn

LineNumberTable:

line 5: 0
  • 注意0: iconst_1即ture用常量1表示

短整型short例子

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ret

{

public static short main(String[] args)

{

return 1234;

}

}

反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...

major version: 52

...

public static short main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)S

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=1, locals=1, args_size=1

0: sipush        1234

3: ireturn

LineNumberTable:

line 5: 0
  • 注意0: sipush 1234

字符型A例子

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ret

{

public static char main(String[] args)

{

return 'A';

}

}

反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...

major version: 52

...

public static char main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)C

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=1, locals=1, args_size=1

0: bipush        65

2: ireturn

LineNumberTable:

line 5: 0
  • 注意0: bipush 65

字符型中例子

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ret

{

public static char main(String[] args)

{

return '中';

}

}

反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...

major version: 52

...

public static char main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)C

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=1, locals=1, args_size=1

0: sipush        20013

3: ireturn

LineNumberTable:

line 5: 0
  • 注意0: sipush 20013

byte类型123列子

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ret

{

public static byte main(String[] args)

{

return 123;

}

}

反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...

major version: 52

...

public static byte main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)B

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=1, locals=1, args_size=1

0: bipush        123

2: ireturn

LineNumberTable:

line 5: 0
  • 注意 0: bipush 123

long类型1234567890123456789L例子

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ret

{

public static long main(String[] args)

{

return 1234567890123456789l;

}

}

反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...

major version: 52

...

\#2 = Long               1234567890123456789l

...

public static long main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)J

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=2, locals=1, args_size=1

0: ldc2_w        \#2                  // long 1234567890123456789l

3: lreturn

LineNumberTable:

line 50
  • 注意0: ldc2_w #2 // long 1234567890123456789l

浮点类型123.456d的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ret

{

public static double main(String[] args)

{

return 123.456d;

}

}

反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...

major version: 52

...

\#2 = Double             123.456d

...

public static double main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)D

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=2, locals=1, args_size=1

0: ldc2_w        \#2                  // double 123.456d

3: dreturn

LineNumberTable:

line 50
  • 注意0: ldc2_w #2 // double 123.456d

浮点类型123.456f的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ret

{

public static float main(String[] args)

{

return 123.456f;

}

}

反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...

major version: 52

...

\#2 = Float              123.456f

...

public static float main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)F

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=1, locals=1, args_size=1

0: ldc           \#2                  // float 123.456f

2: freturn

LineNumberTable:

line 50
  • 注意0: ldc #2 // float 123.456f

参考资料
http://www.vuln.cn/7115