30 September 2017

现在的ARM架构处理器不仅能运行ARM指令集,还能运行Thumb指令集。

其实,Thumb指令集是ARM指令集的一个子集。但它又不仅仅是简单地从中取一部分,而是把32位编码的ARM指令用16位重新编码,旨在节省代码体积。

我们知道,程序的指令与数据一样,也是以二进制的形式(机器语言)放在内存中的,CPU使用时也需要从内存中读取。指令编码变短,代码体积减小,就能节省读取指令时的开销。 尤其是对于一些配置低(比如只支持16位内存访问)的硬件,使用Thumb指令集收益就更明显。

在取到Thumb指令后,CPU会有一个专门的转换模块,把Thumb指令转换为对应的ARM指令来执行。这个转换由专门的硬件完成,不会对执行速度造成影响。也即是说,在执行阶段,Thumb指令与ARM指令效果是一样的。

Thumb指令集具有代码体积小和取指阶段快的优势,而它的不足之处在于无法实现ARM指令集支持的所有操作。它毕竟只是一个子集。 不过Thumb不支持的大多是硬件强相关的操作(操作系统或驱动程序才会涉及),通常的应用程序都能被编译为Thumb指令运行。 编译器可以自行判断是否生成Thumb指令,也可以让用户指定。从上面的分析可以看到,如果无需用到Thumb不支持的特殊操作,可优先选择生成Thumb指令。 不过对于现代硬件来说,运行Thumb的收益能有多少也尚未可知。

对于写C代码的程序员,可以不关注这些,由编译器决定即可。但写汇编的程序员就要注意了!

最近在做汇编优化时,某次编译出现了下面这个错误:

Error: Thumb does not support register post-indexing -- `strh r6,[r0],r1'

确认发现是编译器选择生成Thumb指令,而Thumb不支持上述的strh用法。改为生成ARM指令就不报错了,但Thumb的收益也就没有了。

用ARM还是用Thumb,明白了二者的区别后,就根据具体情况权衡决定吧。