0.1.Thumb指令集
Thumb指令集是ARM指令集的子集,其性能更低,但是代码密度更高,功耗更低。
Thumb指令集分为Thumb-1指令集和Thumb-2指令集,其中Thumb-1指令集是16位指令集,而Thumb-2指令集在Thumb-1的基础上增加了一些32位指令,其性能与ARM指令集类似。
0.2.Cortex-M0汇编语言基本格式
标号
助记符 操作数1, 操作数2, … ;注释
//其中:
(1)标号:用作地址位置的参考,即符号地址
(2)助记符:指令的汇编符号表示
(3)操作数1:目的操作数
(4)操作数2:源操作数
(5)注释:不参与汇编
1. 寄存器访问指令:MOVE
(1)MOV指令
MOV <Rd>, #immed8 ;把立即数immed8(范围0~255)复制到寄存器Rd中
MOV <Rd>, <Rm> ;把寄存器Rm的内容复制到寄存器Rd中
//如:MOV R0, #0x31 ;把16进制立即数31复制到寄存器R0中
//如:MOV R0, R1 ;把寄存器R1的内容复制进R0中
(2)MOVS指令
MOVS <Rd>, <Rm> ;执行MOV的同时更新APSR中标志Z和N的值
(3)MRS指令
MRS <Rd>, <SpecialReg> ;把SpecialReg内容复制到寄存器Rd中
//如:MRS R1, CONTROL ;将CONTROL寄存器的内容复制到寄存器R1中
//该指令不改变APSR中的标志位
(4)MSR指令
MRS <SpecialReg>, <Rd> ;将Rd值复制到SpecialReg中
//该指令会更新APSR寄存器中的N、Z、C、V标志位
2. 存储器访问指令:LOAD
//该指令不改变APSR中的任何标志位
//注意指令后缀:S代表符号拓展;H代表半字(16位);B代表一个字节(8位)
(1)LDR指令
//该指令用于寄存器从存储器那里读数据,取出的数据都是一个整字(32位)的长度。
LDR <Rt>, =立即数 ;把立即数的值直接加载到Rt中
LDR <Rt>, [<Rn>, <Rm>] ;把[Rn+Rm]内容作为地址的存储器存的数据读出来送进Rn
LDR <Rt>, [<Rn>, #immed5] ;读取地址为[Rn+(#immed5<<2)]的存储器中的数据
//注意:零拓展(#immed5<<2)表示立即数的第8位为0(范围0000000~1111111),且满足字对齐关系:
//#immed5 % 4=0(左移2位,空出的低位用0补全)
LDR <Rt>, [PC(SP), #immed8] ;读取地址为[PC(SP)+(#immed8<<2)]的存储器数据
(2)LDRH指令
//功能和LDR指令一样,就是取出的数据都是一个半字(16位)的长度,然后把数据读取到目标寄存器中后,用零填充[31:16]位。
//需要注意的一句:
LDRH <Rt>, [<Rn>, #immed5]
//立即数:零拓展(#immed5<<1)的范围是000000~111111,且满足字对齐:/#immed5%2=0
(3)LDRB指令
//功能和LDR指令一样,就是取出的数据都是一个字节(8位)的长度,然后把数据读取到目标寄存器中后,用零填充[31:8]位。
//需要注意的一句:
LDRB <Rt>, [<Rn>, #immed5]
//立即数:零拓展(#immed5)的范围是00000~11111,不用满足字对齐。
(4)LDRSH指令和LDRSB指令
其指令后缀S表示符号拓展,其意义如下:
LDRSH指令操作数据长度16位([15:0]),后面的字拓展由第15位决定:
第15位为1时,[31:16]补1;第15位为0时,[31:16]补0;
LDRSB指令操作数据长度8位([7:0]),后面的字拓展由第7位决定:
第7位为1时,[31:8]补1;第7位为0时,[31:8]补0。
3. 存储器访问指令:STORE
该指令功能是把寄存器操作的数据存入对应地址的存储器当中,该指令不涉及任何的APSR操作。
(1)STR指令
STR <Rt>, [<Rn>,< Rm>] ;把Rt中的整字数据存到[<Rn>+<Rm>]指向的存储器中
STR <Rt>, [<Rn>,#immed5] ;数据存到[<Rn>+零拓展(#immed5<<2)]指向的存储器中
STR <Rt>, [<SP>,#immed8] ;数据存到[SP+零拓展(#immed5<<2)]指向的存储器中
(2)STRH指令
//功能与STR指令类似,不过从寄存器中拿出的数据只有半字的长度,也就是16位。
STRH <Rt>, [<Rn>,< Rm>] ;把Rt中的[15:0]存到[<Rn>+<Rm>]指向的存储器中
STRH <Rt>, [<Rn>,#immed5] ; 数据存到[<Rn>+零拓展(#immed5<<1)]指向的存储器中
(3)STRB指令
//功能与STR指令类似,不过从寄存器中拿出的数据只有一个字节的长度,也就是8位。
STRB <Rt>, [<Rn>,< Rm>] ;把Rt中的[7:0]存到[<Rn>+<Rm>]指向的存储器中
STRB <Rt>, [<Rn>,#immed5] ; 数据存到[<Rn>+零拓展(#immed5)]指向的存储器中
4. 多数据访问指令:LDM和STM
(1)LDM指令:把存储器的内容加载到多个寄存器当中。
(2)LDMIA指令:把存储器的内容加载到多个寄存器当中,然后把Rn的值更新到最后一个地址+4的值。
(3)STMIA指令:把多个寄存器的内容保存在存储器中,然后把Rn的值递增到寄存器最后一个地址+4的值。
5. 堆栈操作指令:PUSH和POP
(1)PUSH指令:入栈,把一个/多个寄存器保存在堆栈当中,并且更新堆栈指针SP。
比如:PUSH { R0, R1, R2 }
;把R0存到SP-4指向的堆栈空间中
;把R1存到SP-8指向的堆栈空间中
;把R2存到SP-12指向的堆栈空间中
;把SP-12作为SP的新值
(2)POP指令:入栈,把堆栈空间数据读取到存储器当中,并且更新堆栈指针SP。
比如:POP { R0, R1, R2 }
;把R2存到SP指向的堆栈空间中
;把R1存到SP+4指向的堆栈空间中
;把R0存到SP+8指向的堆栈空间中
;把SP+12作为SP的新值
6. 算术运算指令 //略学
(1)加法指令ADD/ADC/ADR等
(2)减法指令SUB/SBC/RSB等
(3)乘法指令MUL
//以上三个都是指令后缀+S代表更新APSR中的各个标志位
(4)比较指令CMP/CMN
7. 逻辑操作指令 //略学
(1)逻辑与指令ANDS
(2)逻辑或指令ORRS
(3)逻辑异或指令EORS
(4)按位取反指令MVNS
(5)按位取反后逻辑与指令BICS
(6)逻辑与后不保存结果只更新APSR指令TST
8. 移位操作指令
//注意三种移位之间的区别:
①算术右移:右移后最后一位由右移前的最后一位补充
②逻辑右移:右移后最后一位由0补充
③循环右移:右移后最后一位由腾出来的右移前最低位补充
//注意移位操作后最后移出去的位(右移为最低位,左移为最高位)保存在APSR的C标志中
(1)算术右移指令ASRS
(2)逻辑右移指令LSRS
(3)循环右移指令RORS
(4)逻辑左移指令LSLS
9. 反序操作指令
(1)字节反序指令REV
(2)半字反序指令REV16
(3)低半字两字节反序指令REVSH
//REVSH指令进行反序后的高半字[31:16]由符号扩展的规则进行填充
10. 扩展操作指令
(1)符号扩展指令SXTB/SXTH
(2)零扩展指令UXTB/UXTH
11. 程序流控制指令
//跳转指令(使用某些条件)让程序跳转入对应指令地址执行指令,使程序可使用子程序、if-else、循环等行为级功能
(1)无条件跳转指令B
(2)有条件跳转指令B<cond><label>
//其他跳转指令就略了
//下面的指令就略看吧,等到看到程序里有了再翻翻资料查一查
12. 存储器屏蔽指令
(1)数据存储器屏蔽指令DMB
(2)数据同步屏蔽指令DSB
(3)指令同步屏蔽指令ISB
13. 异常相关指令
(1)触发SVC异常指令SVC
(2)使能/禁止中断指令CPS
14. 休眠相关指令
(1)WFI:该指令等待中断,停止执行程序直到中断到来或者处理器进入调试状态
(2)WFE:该指令等待事件,停止执行程序直到事件到来(由内部事件寄存器设置)或者处理器进入调试状态
(3)SEV:在多处理环境中,向所有处理器发送事件。
15. 其他指令
(1)空操作指令NOP:用于产生指令对齐,或者产生延迟
(2)断点指令BKPT
(3)任务停止指令YIELD