3.3.2 指令码描述规则
我们直接通过几个例子来学习官方提供的指令码描述规则,先看图3-10。
图3-10 指令码描述规则示例
图3-10是官方文档中对指令的描述,它是一个表,从左至右前三列内容的含义如下。
·第一列叫Format,指明指令码和参数的存储格式,也就是我们在图3-9中介绍的insns内容的组织形式。
·第二列叫Format ID,简称ID,其内容包含两个数字和一到多个后缀字符。其中,第一个数字表示一条完整的指令(即执行该指令需要的指令码和参数)包含几个ushort元素,第二个数字表示这条指令将用到几个寄存器。另外,数字后面的后缀字符也有含义,不过其含义比较琐碎,本文不拟介绍。
·第三列则具体展示了各个参数的用法。读者尤其要注意其中特殊字符的含义,比如“v”“+”“#+”和诸如“kind@”这样的字符串的含义。
了解上述规则后,我们再来看一条稍复杂的规则示例,如图3-11所示。
图3-11 指令码描述规则示例
图3-11中:
·由第一列Format可知一共有A、BBBB、C、D、E、F、G7个参数。每个参数的位长由代表该参数的字符的个数决定。即,除了BBBB是16位长之外,其他6个参数都是4位。Format同时还指明了这7个参数位于ushort元素中的位置。
·由第二列ID的“35c”可知,这种类型的指令需要3个ushort元素,并且需要5个寄存器。
·第三列给出符合第二列ID格式的指令的具体表现形式。其中,[A=x]表示A参数取值为x。“vC”表示某个寄存器,其编号是C的值,“kind@BBBB”表示BBBB为指向xxx_ids的索引。另外,“{}”花括号表示该指令执行时候需要操作的一组寄存器。
有了这些信息就可以解析insns的内容了。Android SDK提供了一个dexdump工具用于解析dex文件,我们看看用它解析dex文件中的函数会得到什么结果,如图3-12所示。
图3-12 dexdump解析函数的结果
dexdump使用的方法为“dexdump-d dex文件”,它能把insns数组的内容翻译成对应的助记符,并解析其中的参数。笔者此处简单介绍00021e处指令码"1200"该如何解析。
·"1200"是指令码的内容。它是16进制,分为"12"和"00",分别构成两个字节。因为该dex文件是Little Endian字节序。所以"12"是低8位,"00"是高八位。
·我们介绍过,操作码+参数组合的话,操作码位于低8位,所以此处可知操作码为"12"。通过查询[3]可知,该指令的标准格式为"1211n",对应的助记符为"const/4 vA,#+B"。
·接下来需要解析这个参数。这需要利用解析格式(Format)"11n"。查询官方文档,11n对应的指令码+参数组合的格式为"B|A|op"。所以,"1200"中,"B|A"取值为"0|0",即B为0,A也为0。
·有了这些信息,"const/4 vA,#+B"就可解析为"const/4 v0,#+0"。
至此,Dex指令码解析的内容就全部介绍完毕,读者现在可以放心去阅读官方文档[3]了。