汇编语言基础知识(cortex-M3 指令)
一、书写格式
标号
操作码 操作数1, 操作数2, ... ; 注释
标号是可选的,可写可不写,但如果有必须顶格写,其作用是让汇编器计算程序转移的地址。
操作码是指令的助记符,其前面必须有一个空格,通常用TAB。
操作数跟在操作码后面,通常,第一个操作数都是本条指令执行结果的存储地。
注释均已";"开头
立即数,也就是高级语言的常量,必须以#开头。
例如:
MOV R0, #0x12 ; R0 <-- 0x12
可以使用EQU来定义常数,且常数的定义必须顶格写。
例如:
PI EQU 3.14.5926
二、
操作 | 汇编指令 |
寄存器值与寄存器值及 C标志相加 | ADC <Rd>, <Rm> |
3位立即数与寄存器值相加 | ADD <Rd>, <Rn>, #<immed_3> |
8位立即数与寄存器值相加 | ADD <Rd>, #<immed_8> |
低寄存器值与低寄存器值相加 | ADD <Rd>, <Rn>, <Rm> |
高寄存器值与低或高寄存器值相加 | ADD <Rd>, <Rm> |
PC加 4(8位立即数) | ADD <Rd>, PC, #<immed_8>*4 |
SP加 4(8位立即数) | ADD <Rd>, SP, #<immed_8>*4 |
SP加 4(7位立即数) | ADD <Rd>, SP, #<immed_7>*4或 ADD SP, SP, #<immed_7>*4 |
寄存器值按位与 | AND <Rd>, <Rm> |
算术右移,移位次数取决于立即数值 | ASR <Rd>, <Rm>, #<immed_5> |
算术右移,移位次数取决于寄存器中的值 | ASR <Rd>, <Rs> |
条件分支 | B<cond> <target address> |
无条件分支 | B<tartet address> |
位清零 | BIC <Rd>, <Rs> |
软件断点 | BKPT <immed_8> |
带链接分支 | BL <Rm> |
比较结果不为零时分支 | CBNZ <Rn>, <label> |
比较结果为零时分支 | CBZ <Rn>, <Rm> |
将寄存器值取反与另一个寄存器值比较 | CMN <Rn>, <Rm> |
与 8位立即数比较 | CMP <Rn>, #<immed_8> |
寄存器比较 | CMP <Rn>, <Rm> |
高寄存器与高或低寄存器比较 | CMP <Rn>, <Rm> |
改变处理器状态 | CPS <effect>, <iflags> |
将高或低寄存器的值复制到另一个高或低寄 存器中 |
CPY <Rd>, <Rm> |
寄存器的值按位异或 | EOR <Rd>, <Rm> |
IT<cond> IT<x> <cond> IT<x><y> <cond> IT<x><y><z> <cond> |
以下一条指令为条件,以下面两条指令为条 件,以下面三条指令为条件,以下面四条指令 为条件 |
多个连续的存储器字加载 | LDMIA <Rn>!, <register> |
将基址寄存器与 5位立即数偏移的和的地址 处的数据加载到寄存器中 |
LDR <Rd>, [<Rn>, #<immed_5*4>] |
将基址寄存器与寄存器偏移的和的地址处的 数据加载到寄存器中 |
LDR <Rd>, [<Rn>, <Rm>] |
将 PC与 8位立即数偏移的和的地址处的数据 加载到寄存器中 |
LDR <Rd>, [PC, #<immed_8>*4] |
将 SP与 8位立即数偏移的和的地址处的数据 加载到寄存器中 |
LDR <Rd>, [SP, #<immed_8>*4] |
将寄存器与 5位立即数偏移的和的地址处的 字节[7:0]加载到寄存器中 |
LDRB <Rd>, [<Rn>, #<immed_5>] |
将寄存器与寄存器偏移的和的地址处的字节 [7:0]加载到寄存器中 |
LDRB <Rd>, [<Rn>, <Rm>] |
将寄存器与 5位立即数偏移的和的地址处的 半字[15:0]加载到寄存器中 |
LDRH <Rd>, [<Rn>, #<immed_5>*2] |
将寄存器与寄存器偏移的和的地址处的半字 [15:0]加载到寄存器中 |
LDRH <Rd>, [<Rn>, <Rm>] |
将寄存器与寄存器偏移的和的地址处的带符 号字节 [7:0]加载到寄存器中 |
LDRSB <Rd>, [<Rn>, <Rm>] |
将寄存器与寄存器偏移的和的地址处的带符 号半字 [15:0]加载到寄存器中 |
LDRSH <Rd>, [<Rn>, <Rm>] |
逻辑左移,移位次数取决于立即数值 | LSL <Rd>, <Rm>, #<immed_5> |
逻辑左移,移位次数取决于寄存器中的值 | LSL <Rd>, <Rs> |
逻辑右移,移位次数取决于立即数值 | LSR <Rd>, <Rm>, #<immed_5> |
逻辑右移,移位次数取决于寄存器中的值 | LSR <Rd>, <Rs> |
将 8位立即数传送到目标寄存器 | MOV <Rd>, #<immed_8> |
将低寄存器值传送给低目标寄存器 | MOV <Rd>, <Rn> |
将高或低寄存器值传送给高或低目标寄存器 | MOV <Rd>, <Rm> |
寄存器值相乘 | MUL <Rd>, <Rm> |
将寄存器值取反后传送给目标寄存器 | MVN <Rd>, <Rm> |
将寄存器值取负并保存在目标寄存器中 | NEG <Rd>, <Rm> |
无操作 | NOP <C> |
将寄存器值按位作逻辑或操作 | ORR <Rd>, <Rm> |
寄存器出栈 | POP <寄存器> |
寄存器和 PC出栈 | POP <寄存器, PC> |
寄存器压栈 | PUSH <registers> |
寄存器和 LR压栈 | PUSH <registers, LR> |
将字内的字节逆向(reverse)并复制到寄存器 中 |
REV <Rd>, <Rn> |
将两个半字内的字节逆向并复制到寄存器中 | REV16 <Rd>, <Rn> |
将低半字[15:0]内的字节逆向并将符号位扩 展,复制到寄存器中。 |
REVSH <Rd>, <Rn> |
循环右移,移位次数由寄存器中的值标识 | ROR <Rd>, <Rs> |
寄存器中的值减去寄存器值和C标志 | SBC <Rd>, <Rm> |
发送事件 | SEV <c> |
将多个寄存器字保存到连续的存储单元中 | STMIA <Rn>!, <registers> |
将寄存器字保存到寄存器与5位立即数偏移的 和的地址中 |
STR <Rd>, [<Rn>, #<immed_5>*4] |
将寄存器字保存到寄存器地址中 | STR <Rd>, [<Rn>, <Rm>] |
将寄存器字保存到SP与8位立即数偏移的和的 地址中 |
STR <Rd>, [SP, #<immed_8> * 4] |
将寄存器字节[7:0]保存到寄存器与 5位立即 数偏移的和的地址中 |
STRB <Rd>, [<Rn>, #<immed_5>] |
将寄存器字节[7:0]保存到寄存器地址中 | STRB <Rd>, [<Rn>, <Rm>] |
将寄存器半字[15:0]保存到寄存器与 5位立即 数偏移的和的地址中 |
STRH <Rd>, [<Rn>, #<immed_5> * 2] |
将寄存器半字[15:0]保存到寄存器地址中 | STRH <Rd>, [<Rn>, #<immed_5> * 2] |
寄存器值减去3位立即数 | STRH <Rd>, [<Rn>, #<immed_5> * 2] |
寄存器值减去8位立即数 | SUB <Rd>, #<immed_8> |
寄存器值减去寄存器值 | SUB <Rd>, <Rn>, <Rm> |
SP减4(7位立即数) | SUB SP, #<immed_7> * 4 |
操作系统服务调用,带8位立即数调用代码 | SVC <immed_8> |
从寄存器中提取字节[7:0],传送到寄存器中, 并用符号位扩展到32位 |
SXTB <Rd>, <Rm> |
从寄存器中提取半字[15:0],传送到寄存器中, 并用符号位扩展到32位 |
SXTH <Rd>, <Rm> |
将寄存器与另一个寄存器相与,测试寄存器中 的置位的位 |
TST <Rn>, <Rm> |
从寄存器中提取字节[7:0],传送到寄存器中, 并用零位扩展到 32位 |
UXTB <Rd>, <Rm> |
从寄存器中提取半字[15:0],传送到寄存器中, 并用零位扩展到32位 |
UXTH <Rd>, <Rm> |
等待事件 | WFE <c> |
等待中断 | WFI <c> |
32位指令
操作 | 汇编指令 |
ADC{S}.W <Rd>, <Rn>, #<modify_constant(immed_12> |
寄存器值与12位立即数及C位相加 |
寄存器值与移位后的寄存器值及C位相加 | ADC{S}.W <Rd>, <Rn>, <Rm>{, <shift>} |
ADD{S}.W <Rd>, <Rn>,#<modify_constant(immed_12)> |
寄存器值与12位立即数相加 |
寄存器值与移位后的寄存器值相加 | ADD{S}.W <Rd>, <Rm>{, <shift>} |
寄存器值与12位立即数相加 | ADDW.W <Rd>, <Rn>, #<immed_12> |
AND{S}.W <Rd>, <Rn>, #<modify_constant(immed_12> |
寄存器值与12位立即数按位与 |
寄存器值与移位后的寄存器值按位与 | AND{S}.W <Rd>, <Rn>, Rm>{, <shift>} |
算术右移,移位次数取决于寄存器值 | ASR{S}.W <Rd>, <Rn>, <Rm> |
条件分支 | B{cond}.W <label> |
位区清零 | BFC.W <Rd>, #<lsb>, #<width> |
将一个寄存器的位区插入另一个寄存器中 | BFI.W <Rd>, <Rn>, #<lsb>, #<width> |
12位立即数取反与寄存器值按位与 | BIC{S}.W <Rd>, <Rn>, #<modify_constant(immed_12)> |
移位后的寄存器值取反与寄存器值按位与 | BIC{S}.W <Rd>, <Rn>, {, <shift>} |
带链接的分支 | BL <label> |
带链接的分支(立即数) | BL<c> <label> |
无条件分支 | B.W <label> |
返回寄存器值中零的数目 | CLZ.W <Rd>, <Rn> |
寄存器值与12位立即数两次取反后的值比较 | CMN.W <Rn>, #<modify_constant(immed_12)> |
寄存器值与移位后的寄存器值两次取反后的 值比较 |
CMN.W <Rn>, <Rm>{, <shift>} |
寄存器值与12位立即数比较 | CMP.W <Rn>, #<modify_constant(immed_12)> |
寄存器值与移位后的寄存器值比较 | CMP.W <Rn>, <Rm>{, <shift>} |
数据存储器排序(barrier) | DMB <c> |
数据同步排序(barrier) | DSB <c> |
寄存器值与12位立即数作异或操作 | EOR{S}.W <Rd>, <Rn>, #<modify_constant(immed_12)> |
寄存器值与移位后的寄存器值作异或操作 | EOR{S}.W <Rd>, <Rn>, <Rm>{, <shift>} |
指令同步排序(barrier) | ISB <c> |
多存储器寄存器加载,加载后加 1或加载前 减 1 |
LDM{IA|DB}.W <Rn>{!}, <registers> |
保存寄存器地址与12位立即数偏移的和的地 址处的数据字 |
LDR.W <Rxf>, [<Rn>, #<offset_12>] |
将寄存器地址与12位立即数偏移的和的地址 处的数据字保存到PC中 |
LDR.W PC, [<Rn>, #<offset_12>] |
将基址寄存器地址的8位立即数偏移的地址 处的数据字保存到PC中,后索引 |
LDR.W PC, #<+/-<offset_8> |
保存基址寄存器地址的8位立即数偏移的地 址处的数据字,后索引 |
LDR.W <Rxf>, [<Rn>], #+/–<offset_8> |
保存基址寄存器地址的8位立即数偏移的地 址处的数据字,前索引 |
LDR.W <Rxf>, [<Rn>, #<+/–<offset_8>]! |
将基址寄存器地址的8位立即数偏移的地址 处的数据字保存到PC中,前索引 |
LDR.W PC, [<Rn>, #+/–<offset_8>]! |
保存寄存器地址左移0, 1, 2或3个位置后的 地址处的数据字 |
LDR.W <Rxf>, [<Rn>, <Rm>{, LSL #<shift>}] |
将寄存器地址左移0, 1, 2或3个位置后的地 址处的数据字保存到PC中 |
LDR.W PC, [<Rn>, <Rm>{, LSL #<shift>}] |
保存PC地址的12位立即数偏移的地址处的数 据字 |
LDR.W <Rxf>, [PC, #+/–<offset_12>] |
将PC地址的12位立即数偏移的地址处的数据 字保存到PC中 |
LDR.W PC, [PC, #+/–<offset_12>] |
保存基址寄存器地址与12位立即数偏移的和 的地址处的字节[7:0] |
LDRB.W <Rxf>, [<Rn>, #<offset_12>] |
保存基址寄存器地址的8位立即数偏移的地 址处的字节[7:0],后索引 |
LDRB.W <Rxf>. [<Rn>], #+/-<offset_8> |
保存寄存器地址左移0, 1, 2或3个位置后的 地址处的字节[7:0] |
LDRB.W <Rxf>, [<Rn>, <Rm>{, LSL #<shift>}] |
保存基址寄存器地址的8位立即数偏移的地 址处的字节[7:0],前索引 |
LDRB.W <Rxf>, [<Rn>, #<+/–<offset_8>]! |
保存PC地址的12位立即数偏移的地址处的字 节 |
LDRB.W <Rxf>, [PC, #+/–<offset_12>] |
保存寄存器地址8位偏移4的地址处的双字, 前索引 |
LDRD.W <Rxf>, <Rxf2>, [<Rn>, #+/–<offset_8> * 4]{!} |
保存寄存器地址8位偏移4的地址处的双字, 后索引 |
LDRD.W <Rxf>, <Rxf2>, [<Rn>], #+/–<offset_8> * 4 |
保存基址寄存器地址与12位立即数偏移的和 的地址处的半字[15:0] |
LDRH.W <Rxf>, [<Rn>, #<offset_12>] |
保存基址寄存器地址的8位立即数偏移的地 址处的半字[15:0],前索引 |
LDRH.W <Rxf>, [<Rn>, #<+/–<offset_8>]! |
保存基址寄存器地址的8位立即数偏移的地 址处的半字[15:0],后索引 |
LDRH.W <Rxf>. [<Rn>], #+/-<offset_8> |
保存基址寄存器地址左移0, 1, 2或3个位置 后的地址处的半字[15:0] |
LDRH.W <Rxf>, [<Rn>, <Rm>{, LSL #<shift>}] |
保存PC地址的12位立即数偏移的地址处的半 字 |
LDRH.W <Rxf>, [PC, #+/–<offset_12>] |
保存基址寄存器地址与12位立即数偏移的和 的地址处的带符号字节[7:0] |
LDRSB.W <Rxf>, [<Rn>, #<offset_12>] |
保存基址寄存器地址的8位立即数偏移的地 址处的带符号字节[7:0],后索引 |
LDRSB.W <Rxf>. [<Rn>], #+/-<offset_8> |
保存基址寄存器地址的8位立即数偏移的地 址处的带符号字节[7:0],前索引 |
LDRSB.W <Rxf>, [<Rn>, #<+/–<offset_8>]! |
保存寄存器地址左移0, 1, 2或3个位置后的 地址处的带符号字节[7:0] |
LDRSB.W <Rxf>, [<Rn>, <Rm>{, LSL #<shift>}] |
保存PC地址的12位立即数偏移的地址处的带 符号字节 |
LDRSB.W <Rxf>, [PC, #+/–<offset_12>] |
保存基址寄存器地址与12位立即数偏移的和 的地址处的带符号半字[15:0] |
LDRSH.W <Rxf>, [<Rn>, #<offset_12>] |
保存基址寄存器地址的8位立即数偏移的地 址处的带符号半字[15:0],后索引 |
LDRSH.W <Rxf>. [<Rn>], #+/-<offset_8> |
保存基址寄存器地址的8位立即数偏移的地 址处的带符号半字[15:0],前索引 |
LDRSH.W <Rxf>, [<Rn>, #<+/–<offset_8>]! |
保存寄存器地址左移0, 1, 2或3个位置后的 地址处的带符号半字[15:0] |
LDRSH.W <Rxf>, [<Rn>, <Rm>{, LSL #<shift>}] |
保存PC地址的12位立即数偏移的地址处的带 符号半字 |
LDRSH.W <Rxf>, [PC, #+/–<offset_12>] |
逻辑左移,移位次数由寄存器中的值标识 | LSL{S}.W <Rd>, <Rn>, <Rm> |
逻辑右移,移位次数由寄存器中的值标识 | LSR{S}.W <Rd>, <Rn>, <Rm> |
将两个带符号或无符号的寄存器值相乘,并 将低32位与寄存器值相加 |
MLA.W <Rd>, <Rn>, <Rm>, <Racc> |
将两个带符号或无符号的寄存器值相乘,并 将低32位与寄存器值相减 |
MLS.W <Rd>, <Rn>, <Rm>, <Racc> |
将12位立即数传送到寄存器中 | MOV{S}.W <Rd>, #<modify_constant(immed_12)> |
将移位后的寄存器值传送到寄存器中 | MOV{S}.W <Rd>, <Rm>{, <shift>} |
将16位立即数传送到寄存器的高半字[31:16] 中 |
MOVT.W <Rd>, #<immed_16> |
将16位立即数传送到寄存器的低半字[15:0] 中,并将高半字[31:16]清零 |
MOVW.W <Rd>, #<immed_16> |
将状态传送到寄存器中 | MRS<c> <Rd>, <psr> |
传送到状态寄存器中 | MSR<c> <psr>_<fields>,<Rn> |
将两个带符号或不带符号的寄存器值相乘 | MUL.W <Rd>, <Rn>, <Rm> |
无操作 | NOP.W |
将寄存器值与12位立即数作逻辑“或非”操作 | ORN{S}.W <Rd>, <Rn>, #<modify_constant(immed_12)> |
将寄存器值与移位后的寄存器值作逻辑“或 非”操作 |
ORN[S}.W <Rd>, <Rn>, <Rm>{, <shift>} |
将寄存器值与12位立即数作逻辑“或”操作 |
ORR{S}.W <Rd>, <Rn>, #<modify_constant(immed_12) |
将寄存器值与移位后的寄存器值作逻辑“或 ” 操作 |
ORR{S}.W <Rd>, <Rn>, <Rm>{, <shift>} |
将位顺序逆向 | RBIT.W <Rd>, <Rm> |
将字内的字节逆向 | REV.W <Rd>, <Rm> |
将每个半字内的字节逆向 | REV16.W <Rd>, <Rn> |
将低半字内的字节逆向并用符号扩展 | REVSH.W <Rd>, <Rn> |
循环右移,移位次数取决于寄存器中的值 | ROR{S}.W <Rd>, <Rn>, <Rm> |
寄存器值与12位立即数相减 | RSB{S}.W <Rd>, <Rn>, #<modify_constant(immed_12)> |
寄存器值与移位后的寄存器值相减 | RSB{S}.W <Rd>, <Rn>, <Rm>{, <shift>} |
寄存器值与12位立即数及C位相减 | SBC{S}.W <Rd>, <Rn>, #<modify_constant(immed_12)> |
寄存器值与移位后的寄存器值及C位相减 | SBC{S}.W <Rd>, <Rn>, <Rm>{, <shift>} |
将所选的位复制到寄存器中并用符号扩展 | SBFX.W <Rd>, <Rn>, #<lsb>, #<width> |
带符号除法 | SDIV<c> <Rd>,<Rn>,<Rm> |
发送事件 | SEV<c> |
将带符号半字相乘并用符号扩展到2个寄存 器值 |
SMLAL.W <RdLo>, <RdHi>, <Rn>, <Rm> |
两个带符号寄存器值相乘 | SMULL.W <RdLo>, <RdHi>, <Rn>, <Rm> |
带符号饱和操作 | SSAT <c> <Rd>, #<imm>, <Rn>{, <shift>} |
多个寄存器字保存到连续的存储单元中 | STM{IA|DB}.W <Rn>{!}, <registers> |
寄存器字保存到寄存器地址与12位立即数偏 移的和的地址中 |
STR.W <Rxf>, [<Rn>, #<offset_12>] |
寄存器字保存到寄存器地址的8位立即数偏 移的地址中,后索引 |
STR.W <Rxf>, [<Rn>], #+/–<offset_8> |
寄存器字保存到寄存器地址移位0, 1, 2或3 个位置的地址中 |
STR.W <Rxf>, [<Rn>, <Rm>{, LSL #<shift>}] |
寄存器字保存到寄存器地址的8位立即数偏 移的地址中,前索引 |
STR{T}.W <Rxf>, [<Rn>, #+/–<offset_8>]{!} |
寄存器字节[7:0]保存到寄存器地址的 8位立 即数偏移的地址中,前索引 |
STRB{T}.W <Rxf>, [<Rn>, #+/–<offset_8>]{!} |
寄存器字节[7:0]保存到寄存器地址与 12位 立即数偏移的和的地址中 |
STRB.W <Rxf>, [<Rn>, #<offset_12>] |
寄存器字节[7:0]保存到寄存器地址的 8位立 即数偏移的地址中,后索引 |
STRB.W <Rxf>, [<Rn>], #+/–<offset_8> |
寄存器字节保存到寄存器地址移位0, 1, 2或 3个位置的地址中 |
STRB.W <Rxf>, [<Rn>, <Rm>{, LSL #<shift>}] |
存储双字,前索引 | STRD.W <Rxf>, <Rxf2>, [<Rn>, #+/–<offset_8> * 4]{!} |
存储双字,后索引 | STRD.W <Rxf>, <Rxf2>, [<Rn>], #+/–<offset_8> * 4 |
寄存器半字[15:0]保存到寄存器地址与 12位 立即数偏移的和的地址中 |
STRH.W <Rxf>, [<Rn>, #<offset_12>] |
寄存器半字保存到寄存器地址移位0, 1, 2或 3个位置的地址中 |
STRH.W <Rxf>, [<Rn>, <Rm>{, LSL #<shift>}] |
寄存器半字保存到寄存器地址的8位立即数 偏移的地址中,前索引 |
STRH{T}.W <Rxf>, [<Rn>, #+/–<offset_8>]{!} |
寄存器半字保存到寄存器地址的8位立即数 偏移的地址中,后索引 |
STRH.W <Rxf>, [<Rn>], #+/–<offset_8> |
寄存器值与12位立即数相减 | SUB{S}.W <Rd>, <Rn>, #<modify_constant(immed_12)> |
寄存器值与移位后的寄存器值相减 | SUB{S}.W <Rd>, <Rn>, <Rm>{, <shift>} |
寄存器值与12位立即数相减 | SUBW.W <Rd>, <Rn>, #<immed_12> |
将字节符号扩展到32位 | SXTB.W <Rd>, <Rm>{, <rotation>} |
将半字符号扩展到32位 | SXTH.W <Rd>, <Rm>{, <rotation>} |
表格分支字节 | TBB [<Rn>, <Rm>] |
表格分支半字 | TBH [<Rn>, <Rm>, LSL #1] |
寄存器值与12位立即数作逻辑“异或”操作 | TEQ.W <Rn>, #<modify_constant(immed_12)> |
寄存器值与移位后的寄存器值作逻辑“异或 ” 操作 |
TEQ.W <Rn>, <Rm>{, <shift} |
寄存器值与12位立即数作逻辑“与”操作 | TST.W <Rn>, #<modify_constant(immed_12)> |
寄存器值与移位后的寄存器值作逻辑“与”操 作 |
TST.W <Rn>, <Rm>{, <shift>} |
将寄存器的位区复制到寄存器中,并用零扩 展到32位 |
UBFX.W <Rd>, <Rn>, #<lsb>, #<width> |
无符号除法 | UDIV<c> <Rd>,<Rn>,<Rm> |
两个无符号寄存器值相乘并与两个寄存器值 相加 |
UMLAL.W <RdLo>, <RdHi>, <Rn>, <Rm> |
两个无符号寄存器值相乘 | UMULL.W <RdLo>, <RdHi>, <Rn>, <Rm> |
无符号饱和操作 | USAT <c> <Rd>, #<imm>, <Rn>{, <shift>} |
将无符号字节复制到寄存器中并用零扩展到 32位 |
UXTB.W <Rd>, <Rm>{, <rotation>} |
将无符号半字复制到寄存器中并用零扩展到 32位 |
UXTH.W <Rd>, <Rm>{, <rotation>} |
等待事件 | WFE.W |
等待中断 | WFI.W |