Dalvik源码分析(二)dex文件分析(1)

本篇主要描述.dex文件中用到的LEB128,关于.dex文件的具体格式下篇再讲。

.dex文件中使用的数据类型如下图所示:

Dalvik源码分析(二)dex文件分析(1)_第1张图片

这里我们可以看到出现了几个我们不熟悉的类型sleb128, usleb128, usleb128p1.

通过他们的描述文件可以了解到这几个类型都是基于LEB128,那下面我们就先来了解一下LEB128是个啥东东。

 

其实,LEB128就是一种利用编程编码(variable-length code)压缩数据的一种格式,它能够以较少的字节存储任意大小的数字。有2种类型的LEB128:有符号的LEB128(signed LEB128)和无符号的LEB128(unsigned LEB128 )。下面以无符号LED128为例说明计算过程。

unsigned LEB128

编码:

 在对一个无符号数编码之前首先将其表示成二进制形式,然后将二进制表示每7位分为一组(不足的位补0)。将分组后的每一组添加一个最高位(第一组补0,其他各组补1)形成每组8bits,最后将每个组表示成16进制形式即可完成编码。

下面以数字624485 为例说明:

我们可以看到,原本需要4个字节的数字被压缩为3个字节表示。

Dalvik中编码过程为:

DEX_INLINE u1* writeUnsignedLeb128(u1* ptr, u4 data)

{

    while (true) {

        u1 out = data & 0x7f; //提取数据的低7bit

        if (out != data) {

            *ptr++ = out | 0x80; //置最高位为1

            data >>= 7;

        } else {

            *ptr++ = out;

            break;

        }

    }

    return ptr;

}

解码:

解码过程中,每次读取一个字节(8bits)判断其最高位是否为1(为1说明还有其他字节,0说明是最后一个字节,解码结束),然后提取出低7位。处理完所有的字节即可得到原来保存的值。

 

Dalvik解码的代码为:

DEX_INLINE int readUnsignedLeb128(const u1** pStream) {

    const u1* ptr = *pStream;

    int result = *(ptr++);

 

    if (result > 0x7f) { //判断第一个字节的高位是否为1

        int cur = *(ptr++); //cur指向第二个字节

                   //result为第一个字节的7位加上第二个字节的7

        result = (result & 0x7f) | ((cur & 0x7f) << 7);

        if (cur > 0x7f) {

            cur = *(ptr++); //cur指向第三个字节

            result |= (cur & 0x7f) << 14;

            if (cur > 0x7f) {

                cur = *(ptr++); //cur指向第四个字节

                result |= (cur & 0x7f) << 21;

                if (cur > 0x7f) {

                    /*

                     * Note: We don't check to see if cur is out of

                     * range here, meaning we tolerate garbage in the

                     * high four-order bits.

                     */

                    cur = *(ptr++); //cur指向第五个字节

                    result |= cur << 28;

                }

            }

        }

}

 

代码中与0x7f比较是为了判断最高位是否为1 (因为如果值大于0x7f的话其最高位肯定为1 )。

cur & 0x7f是为了获取cur中低7位。

 

对于有符号的数,编码过程基本相似。只是其二进制为补码表示,编码后最高字节的次高位表示符号位。

Dalvik没有给出编码signedLeb128的方法(不知为啥,继续研究),

下面给出Wiki上的伪代码以示说明:

more = 1;

negative = (value < 0);

size = no. of bits in signed integer;

while(more) {

  byte = low order 7 bits of value;

  value >>= 7;

  /* the following is unnecessary if the implementation of >>= uses an

     arithmetic rather than logical shift for a signed left operand */

  if (negative)

    value |= - (1 <<(size - 7)); /* sign extend */

 

  /* sign bit of byte is second high order bit (0x40) */

  if ((value == 0 && sign bit of byte is clear) || (value == -1 && sign bit of byte is set))

    more = 0;

  else

    set high order bit of byte; //置最高位为1

  emit byte;

}

 

你可能感兴趣的:(数据压缩,dalvik,.dex文件,leb128)