• RISC指令集的芯片对于内存/外设只有读写两个操作
    • ARM汇编指令按类型大致可分为4类:内存R/W、运算、跳转/分支、比较
      • image.png
      • 掌握着4类指令就基本足够了
    • ARM架构芯片有三种指令集:ARM、Thumb、Thumb2;表示一条汇编指令用16/32bit来表示
    • Thumb指令集用16bit表示一条指令,ARM用32bit表示一条指令,Thumb2支持16/32bit来表示一条指令
    • Thumb指令集精简了程序代码段的大小,提高了代码密度
    • ARM架构芯片一般都同时支持ARM/Thumb两种不同指令集,在程序状态寄存器PSR中有一个bit用来表示运行的是Thumb指令还是ARM指令(bit24:1 表示Thumb; 0 表示ARM)

      ①ARM指令集,这是32位的,每条指令占据32位,高效,但是太占空间 ②Thumb指令集,这是16位的,每条指令占据16位,节省空间 要节省空间时用Thumb指令,要效率时用ARM指令。 一个CPU既可以运行Thumb指令,也能运行ARM指令。 怎么区分当前指令是Thumb还是ARM指令呢? 程序状态寄存器中有一位,名为“T”,它等于1时表示当前运行的是Thumb指令。

    • 程序中可能一部分代码用的是ARM指令集(高效),一部分用的是Thumb指令集(节省空间)

    • 可通过CODE16/CODE32来表示当前代码段是Thumb/ARM指令集
    • 那么要怎么告诉CPU,当前(即将)要执行的是Thumb指令还是ARM指令呢?
      • BX Fun_addr //用Fun_addr的bit0=0来表示执行的是ARM指令集
      • BX Fun_addr+1 //bit0=1表示执行的是Thumb指令集
      • Fun_addr的bit0=0时,执行的是ARM指令;Fun_addr的bit0=1时,执行的是Thumb指令
    • 对于ARM7/ARM9/Cortex-A7芯片,都是支持ARM/Thumb两种指令集
    • 对于Cortex-M3/M4芯片,又引进了Thumb2指令集;对于Thumb2指令集,既支持16位的指令也支持32位的指令,两者可以混合编程,并不需要用CODE16/CODE32来指定是16bit/32bit指令
    • 使用Thumb2指令集时,可以写入各种指令,可以是16位的也可以是32位的,当CPU来执行这条指令时会自动分辨是16/32位的
    • 针对ARM/Thumb/Thumb2三个指令集,采用统一的汇编语言UAL(Unified Assembly Language),我们并不需要去区分这些指令集
    • 可以在程序前面用CODE32/CODE16/THUMB表示指令集:ARM/Thumb/Thumb2
    • 对于编程来说,三种指令集下使用的语法、指令都是一摸一样的
    • 我们并不需要写出多么复杂的汇编程序,一般在设置完栈后就用C语言来写函数了
    • 汇编指令UAL格式(数据处理类指令为例):
      • image.png
      • operation表示各类汇编指令
      • cond表示condition,指什么条件下执行这条指令
      • S表示这条指令执行后会不会影响到程序状态寄存器PSR
      • Rd表示目的寄存器
      • Rn、Operand2是两个源操作数
    • cond有多种取值,如:
      • image.png
    • 立即数
      • 立即数不能是任意的值
      • 例如:”MOV R0, #VAL”指令是16位或32位,需要若干位表示MOV、若干位表示R0,剩下的位才用来表示VAL,剩下的位无法保存任意数值的VAL,所以VAL必须符合某些规则
      • image.png
      • 立即数:是某个8位数加循环移位偶位数得到的数
    • 如果就是向让R0等于某个数(任意的,可能不符合规则的),怎么办?
      • 可以使用伪指令,如LDR RO,=VAL
      • “伪指令”,就是假的、不存在的指令。
      • 注意LDR作为“伪指令”时,指令中有一个“=”,否则它就是真实的LDR(load regisgter)指令了
      • 编译器会把伪指令替换成真实的指令
    • 用得比较多的伪指令还有ADR:

      • ADR的意思是:address,用来读某个标号的地址
      • image.png

        ADR loop loop ADD R0,R0,1

      • 实际也会转换成真实的指令

      • ADD R0,PC,#VAL //val在链接时确定,是当前ADR伪指令和loop之间的偏移offset
    • 使用keil MDK工具编译程序时,其内部自带的编译器的语法叫armasm(ARMCC);使用arm-gcc(GCC)工具编译程序时,其语法称为GNU语法
      • image.png
      • 两种语法类似,但在关键字上有些差别