所有的ARM Cortex-M都是基于Thumb-2技术(允许混合使用16位和32位指令)。
早期的ARM处理器是支持ARM的32位指令集,功能强大,但是随着移动电话等应用不断发展,功耗和成本变得十分关键,因此16位指令集Thumb也应运而生。1995年ARM发布了ARM7TDMI处理器,可以在ARM和Thumb状态之间进行切换,与等价的ARM代码相比,减小了代码密度。
然而Thumb仍然有一些局限性,例如操作可选的寄存器、可用的寻址模式及用于数据或地址的立即数范围较小等。
2003年,ARM提出了Thumb-2技术,这种技术可以同时使用16位和32位指令集。还可以使用之前只能用ARM指令集实现的多数操作。2006年,ARM发布了Cortex-M3处理器,它不再支持ARM指令集。
ARM指令集架构还在不断发展中,目前已经有了ARMv8架构,支持64位操作指令集。
为了将回路面积降到最低,Cortex-M0/M0+/M1处理器只支持多数16位指令和部分32位指令。Cortex-M3支持的32位指令更多,Cortex-M4处理器支持剩下的SIMD等DSP提升指令集可选的浮点指令。
Cortex-M指令集是向上兼容的,M0/M0+是可以在M3上运行的。对于同一种操作,16位和32位版本的指令所需要的时间是相同的。
对于开发者而言,一般的数据处理和I/O控制任务,Cortex-M0/M1已经完全可以应付。若需要处理更多复杂数据或是对速度有较高要求,可能需要升级到Cortex-M3,若对于DSP应用或浮点计算有要求,Cortex-M4会是很好的选择。
了解一些指令集对于用户而言在调试工程时能更好的理解程序。
汇编语言对于多数软件开发人员都不是必要的,但是了解一些汇编对开发很有帮助。不同供应商的汇编工具具有不同的语法,多数情况下,汇编指令都是一样的,但是汇编伪指令、定义、标号和注释会有差异。
对于ARM汇编,格式如下:
label
mnemonic operand1,operand2,... ;注释
label是地址位置(可选),mnemonic是助记符,后面是操作数。
以ARM的数据处理指令为例,第一个操作数为操作的目的,对于读指令,第一个操作数为数据被加载的寄存器。注意:
1.有些指令可能存在不同类型的操作数,这样会得到不同的指令编码。
2.指令中操作数的个数取决于指令的种类,操作数的语法也可能各不相同。
3.分号后的文字为注释(不同汇编器语法可能不同),不会影响运行,例如 MOVS R0, # 0x12 ;设置R0为0x12
汇编代码的一个常见特性为定义常量,增加程序可读性;多数汇编工具允许将数据插入到程序当中,例如可以在程序存储器的特定位置定义数据,并用读指令访问。
LDR R3, = MY_NUM ;
LDR R4, [R3] ;
...
LDR R0, = HELLO_TEXT ;
BL PrintText ;
...
ALIGN 4
MY_NUM DCD 0x12345678 ;
HELLO_TEXT DCB"hello/n",0 ;
DCD用于插入字大小的数据,DCB用于将字大小的数据插入到程序,在使用LDR伪指令将数据加载到寄存器中时,前缀应该使用“=”,立即数较小时,前缀应该使用“#”;
ARM和GNU汇编器的多个伪指令可以将数据插入到程序中,如下图所示:
对于一些ARM处理器的汇编器,有些指令后面会跟着后缀,例如:
1.S——更新APSR(应用程序状态寄存器)
2.EQ,NE,CS,CC,MI,PL,...——条件执行,EQ=等于,NE=不等于,LT=小于,GT=大于
3..N,.W——指定使用的是16位指令或32位指令
4..64,F64——指定64位双精度运算
为了让不同架构的ARM处理器符合同一个汇编语言,较新的ARM开发工具已经支持UAL,与之前的ARM7TDMI相比,主要区别是不管目的寄存器是否和其中一个源寄存器相同,都使用三个操作数以及S后缀更加明确,ARSR的更新都应该有S后缀。
.W后缀表示32位指令,如果没有后缀,汇编器一般会选择更小的来提高代码密度。