本篇主要描述.dex文件中用到的LEB128,关于.dex文件的具体格式下篇再讲。 编程
.dex文件中使用的数据类型以下图所示: 编码
这里咱们能够看到出现了几个咱们不熟悉的类型sleb128, usleb128, usleb128p1. spa
经过他们的描述文件能够了解到这几个类型都是基于LEB128,那下面咱们就先来了解一下LEB128是个啥东东。 code
其实,LEB128就是一种利用编程编码(variable-length code)压缩数据的一种格式,它可以以较少的字节存储任意大小的数字。有2种类型的LEB128:有符号的LEB128(signed LEB128)和无符号的LEB128(unsigned LEB128 )。下面以无符号LED128为例说明计算过程。 it
unsigned LEB128 io
编码: 数据类型
在对一个无符号数编码以前首先将其表示成二进制形式,而后将二进制表示每7位分为一组(不足的位补0)。将分组后的每一组添加一个最高位(第一组补0,其余各组补1)造成每组8bits,最后将每一个组表示成16进制形式便可完成编码。 二进制
下面以数字624485 为例说明: 方法
咱们能够看到,本来须要4个字节的数字被压缩为3个字节表示。 im
Dalvik中编码过程为:
DEX_INLINE u1* writeUnsignedLeb128(u1* ptr, u4 data)
{
while (true) {
u1 out = data & 0x7f; //提取数据的低7位bit
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;
}