指令码的执行方式,大致有两种:解释和编译。两者都是以二进制目标机器码为输入,所采取的执行策略不同。
何为解释?就是说将机器码逐条读出,每读一条就进行解码、执行。实现相对简单,一般用高级语言编写解释器,移植性好。能够实现精确控制,方便中断、异常处理,且能实现目标硬件功能的完全模拟。缺点是效率低下。
编译,就是把二进制机器码按块进行转换,生成本地机器能够直接运行的指令码,并存放入缓冲区。它能够实现代码的高效运行,前提是缓冲区的代码会被反复调用。
通常情况下解释执行的速度慢于编译执行。原因是解释执行时,不管以前有没有执行过,都要对当前的指令进行分析译码,而编译执行能够记住过去执行过代码,当再次调用时直接从缓冲区中取出编译好的代码直接执行。举个例子,比如一段循环代码:sub这行它会执行100次,编译执行时只在第1次执行时运行编译器,然后的99次均直接执行缓冲区中的本机代码;解释执行要有100次调用解释器的开销。
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
一般编译执行的流程如下:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
编译器编写时要考虑的问题主要有:基本块的划分,中断/异常模拟的实现,本机机器指令相关(如寄存器分配,指令编码等)。
有张图,展示了Mac上某x86模拟器动态编译执行的架构: