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

本篇主要描述.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; //提取數據的低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;

}

相關文章
相關標籤/搜索