基于X86平台的ARM指令集模拟器的设计
指令执行3个过程。图3描述了指令集模拟器内核的总体架构。如图所示,整个内核包含程序加载模块、指令译码模块、取指模块、指令调度与模拟模块、寄存器模拟模块和数据存储模块。在此模拟器中,存储模块不做实现,调用gdb中的相应模块。
2.2 ARM指令集模拟器的流程设计
本模拟器是按照解释型模拟器的模拟策略设计的。解释型指令集模拟器基本上是以软件实现的虚拟机,它以解释的形式在宿主机上执行加载的目标代码,它的主体是一个具有3步过程的循环体,分别对应取指令、指令译码、指令执行3步操作。因此本ARM指令集模拟器的核心流程就是加载程序,之后进入读取指令、指令译码和指令执行的循环体中,当所有目标代码都执行之后结束并显示运行结果。整个流程如图4指令模拟器的工作流程所示。
2.3 ARM指令集模拟器的主要功能模块设计
2.3.1 指令译码模块
指令译码模块的功能就是根据ARM指令集编码,将要执行的二进制指令译码成操作码、操作数、条件码等指令模拟需要的信息。指令集模拟器的每一模拟步模拟一条指令的取指令、译码、执行等各个阶段,因此指令集模拟器中的指令译码与实际ARM处理器的译码并不是完全对应,同时也不会影响模拟的正确性。
在指令译码模块中,本文采用分类的思想,将指令集按照一定的规律进行分类解析,逐步解析,找到最终指令所对应的解析函数。这样做的目的是为了减少判断指令时的条件判断次数,采用分治的思想提高指令译码的效率。不过要想对指令译码效率有显著性的提高,还是要采用改进型的工作流程,主要原因是在指令译码的过程中,会出现大量的重复译码,所以改进型的工作流程中提出的指令缓存技术会很好的提高译码效率,减少重复的译码工作。
2.3.2 指令模拟与调度模块
指令模拟与调度功能模块是指令集模拟器的核心部分,也是实现代码量最大的部分,主要包括与虚拟指令集定义对应的一系列指令模拟函数、指令执行控制函数、指令翻译调度函数、中断处理函数以及一些公用函数。指令执行控制函数负责控制整个模拟过程,反汇编结果文件加载完毕后,程序就进入核心部分的模拟循环;指令翻译调度函数负责将目标指令转化为虚拟指令形式,然后指令模拟函数按照相应指令的功能定义完成指令的模拟,模拟结果是修改存储器、寄存器值:公用函数主要包括寻址方式判别、指令操作数分析、指令条件码判别、移位操作、ALU操作以及寄存器访问等。指令模拟与调度的循环过程如下:
1)取指令
该模拟器的输入是二进制可执行文件,因此取指令时,根据PC值取得的当前的指令,进行译码。
2)翻译
调用指令翻译函数获得虚拟指令。
3)调度
根据指令类型,调用相应的指令模拟函数。
4)执行
指令模拟函数对指令进行模拟。
5)中断检测与调度
为了对中断系统进行模拟,本文定义了对应于FIQ、IRQ的标志变量,可以改变他们来模拟外部中断输入,每条指令模拟结束后,必须检测上述两个标志,如果检测到中断发生,则调用相应的异常进入函数,PC被设定为中断服务程序入口地址。
6)更新PC值
如果本次循环没有发生指令跳转、加载PC及中断,PC顺序移向下一条指令。
2.4 ARM指令集模拟器的内核设计
模拟器内核结构如图5所示。
2.4.1 内核解码模块设计
指令模拟器内核中的解码模块包括取指令模型和指令转换模型两部分内容,取指令模型介绍了内核程序如何从加载的目标代码中取出逐条指令,指令转换模型介绍了取出的逐条指令是如何转换成中间语言指令来实现的。
1)取指令模型
本文设计的模拟器中取指令模型结构如图6所示,包括指令计数器、指令格式解析器、指令格式解析器、取指令逻辑控制器和指令地址更新逻辑。指令计数器是处理器都会有的一个寄存器。不同的处理器有不同的表现形式。
2)指令的转换模型
指令译码就是根据ARM指令集编码,将要执行的指令译成操作码、操作数、条件码等指令仿真需要的信息。译码的重点在于获取不同寻址方式下的操作数,通过分析指令字助记符和指令码,可以很方便地得到不同寻址方式的操作数。由于本文设计的指令集虚拟模拟ARM的指令集,所以加入指令转换模型,指令转换是将一条目标机器指令转换为一条或几条中间可执行指令集的过程。转换工作由指令转换器完成。其工作模型如图7所示,一条源指令经过指令译码模块翻译,生成一系列的中间语言队列,在本模拟器中,中间语言就是能在X86平台上运行的汇编语言。
2.4.2 内核指令模拟与调度模块
指令调度就是把指令字与完成相应操作的功能函数对应起来,使得仿真时取到该指令后能知道该调用哪个执行过程。本文是基于传统的解释型仿真策略,其主体是一个大的switch结构,并使用case语句。这种设计模型会影响模拟速度,由于case语句的种类非常多,所以在今后的工作中,这里将会是一个重点的研究对象,可以采用hash结构、压缩算法或者指令缓存来提高指令译码的执行效率,这也将会是模拟器的整体执行效率得到一个很大的提高。
指令模拟执行模块把指令分类处理并采用数据获取和数据操作相分离的方法,使得执行函数更具有通用性,当新的指令系统添加时,只需要添加相应的寻址方式和原系统中没有的指令执行过程,就能完成添加指令集的操作,提高了系统设计的可扩展性。
3 结束语
本文是针对嵌入式开发现阶段的主要存在的问题,即传统低下的开发效率和当下对较短市场开发周期的要求之间的矛盾,提出了ARM指令集模拟器的设计和实现方法。以及对指令集模拟技术的介绍和掌握。目前,与嵌入式系统相关的软件开发复杂度越来越高,因此指令集模拟器的发展前景十分乐观。
- 第7章 NASM的使用教程(X86汇编教程)(12-01)
- 第1章 从机器码到开发语言(X86汇编教程)(12-01)
- 第9章 内存操作(X86汇编教程)(12-01)
- 第3章 存储器(X86汇编教程)(12-01)
- 第2章 一些数据单位(X86汇编教程)(12-01)
- 第11章 栈(X86汇编教程)(12-01)