zoukankan      html  css  js  c++  java
  • Java逆向系列-基础指令:操作数栈

    本地变量和操作数栈

    本地变量数组(Local Variable Array)

    本地变量的数组包括方法执行所需要的所有变量,包括 this 的引用,所有方法参数和其他本地定义的变量。对于那些方法(静态方法 static method)参数是以零开始的,对于实例方法,零为 this 保留。

    所有的类型都在本地变量数组中占一个槽(entry),而 long 和 double 会占两个连续的槽,因为它们有双倍宽度(64-bit 而不是 32-bit)。

    操作数栈(Operand Stack)

    操作数栈(也可以称之为表达式栈(Expression Stack))在执行字节码指令的时候使用,它和通用寄存器在 native CPU 中使用的方式类似。大多数 JVM 字节码通过 pushing,popping,duplicating,swapping,或生产消费值的操作使用操作数栈。


    看一个运算的例子

    public class calc
    {
    public static int half(int a)
    {
    return a/2;
    }
    }

    编译

    javac calc.java

    反编译

    javap -c -verbose calc.class

    反编译结果

    ...
    major version: 52
    ...
    public static int half(int);
    descriptor: (I)I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=2, locals=1, args_size=1
    0: iload_0
    1: iconst_2
    2: idiv
    3: ireturn
    LineNumberTable:
    line 5: 0

    iload_0 第0个变量(即变量a)压入操作数栈

    +-------+
    | stack |
    +-------+
    |   a   |
    +-------+

    iconst_2 将2压入操作数栈

    +-------+
    | stack |
    +-------+
    |   2   |
    |   a   |
    +-------+

    idiv  操作数栈中的前两个int相除,并将结果压入操作数栈顶

    +-------+
    | stack |
    +-------+
    | result|
    +-------+

    ireturn  返回栈顶元素

    例子2,复杂一点的例子,处理双精度的值

    public class calc
    {
    public static double half_double(double a)
    {
    return a/2.0;
    }
    }

    反编译

    ...
    major version: 52
    ...
    #2 = Double             2.0d
    ...
    public static double half_double(double);
    descriptor: (D)D
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=4, locals=2, args_size=1
    0: dload_0
    1: ldc2_w        #2                  // double 2.0d
    4: ddiv
    5: dreturn
    LineNumberTable:
    line 5: 0

    ldc2_w指令是从常量区装载2.0d,另外,其他三条指令有d前缀,意思是他们使用double数据类型。

    例子3,两个参数

    public class calc
    {
    public static int sum(int a, int b)
    {
    return a+b;
    }
    }

    反编译

    ...
    major version: 52
    ...
    public static int sum(int, int);
    descriptor: (II)I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=2, locals=2, args_size=2
    0: iload_0
    1: iload_1
    2: iadd
    3: ireturn
    LineNumberTable:
    line 5: 0

    iload_0 第0个变量(即变量a)压入操作数栈

    +-------+
    | stack |
    +-------+
    |   a   |
    +-------+

    iload_1 第1个变量(即变量b)压入操作数栈

    +-------+
    | stack |
    +-------+
    |   b   |
    |   a   |
    +-------+

    iadd 操作数栈中的前两个int相加,并将结果压入操作数栈顶

    +-------+
    | stack |
    +-------+
    | result|
    +-------+

    ireturn 返回栈顶元素

    例子4,类型改为长整型

    public class calc
    {
    public static long lsum(long a, long b)
    	{
    		return a+b;
    	}
    }

    反编译

    ...
    major version: 52
    ...
    public static long lsum(long, long);
    descriptor: (JJ)J
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=4, locals=4, args_size=2
    0: lload_0
    1: lload_2
    2: ladd
    3: lreturn
    LineNumberTable:
    line 5: 0

    可以看到压入第二个参数的时候为lload_2,可见lload_0占了两个槽(entry)

    例子5,混合运算

    public class calc
    {
    public static int mult_add(int a, int b, int c)
    {
    return a*b+c;
    }
    }

    反编译

    ...
    major version: 52
    ...
    public static int mult_add(int, int, int);
    descriptor: (III)I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=2, locals=3, args_size=3
    0: iload_0
    1: iload_1
    2: imul
    3: iload_2
    4: iadd
    5: ireturn
    LineNumberTable:
    line 5: 0

    iload_0 第0个变量(即变量a)压入操作数栈

    +-------+
    | stack |
    +-------+
    |   a   |
    +-------+

    iload_1 第1个变量(即变量b)压入操作数栈

    +-------+
    | stack |
    +-------+
    |   b   |
    |   a   |
    +-------+

    imul 操作数栈中的前两个int相乘,并将结果压入操作数栈顶

    +-------+
    | stack |
    +-------+
    |result1|
    +-------+

    iload_2 第2个变量(即变量c)压入操作数栈

    +-------+
    | stack |
    +-------+
    |   c   |
    |result1|
    +-------+

    iadd 操作数栈中的前两个int相加,并将结果压入操作数栈顶

    +-------+
    | stack |
    +-------+
    |result2|
    +-------+

    ireturn 返回栈顶元素

    本文参考:逆向工程权威指南.下册.pdf 和http://blog.51cto.com/7317859/2105269

  • 相关阅读:
    viewpager切换时底下的背景图标动画切换
    hdu 1594水题
    hdu 4256大水题
    hdu 1856并查集
    hdu4247水题
    hdu 4252单调栈
    hdu 4248排列问题
    hdu 1210
    hdu4245
    hdu 1593找规律题
  • 原文地址:https://www.cnblogs.com/llhl/p/9648612.html
Copyright © 2011-2022 走看看