ARM备忘

http://www.keil.com/

助记符 简单说明 页码 体系结构[1]
ADCADD 带进位加法,加法 ADD、SUB、RSB、ADC、SBC 和 RSC 全部
ADR 加载相对程序或相对寄存器地址(短范围) ADR 全部
ADRL 伪指令 加载相对程序或相对寄存器地址(中等范围) ADRL 伪指令 x6M
AND 逻辑“与” AND、ORR、EOR、BIC 和 ORN 全部
ASR 算术右移 ASR、LSL、LSR、ROR 和 RRX 全部
B 跳转 B、BL、BX、BLX 和 BXJ 全部
BFCBFI 位域清零和插入 BFC 和 BFI T2
BIC 位清零 AND、ORR、EOR、BIC 和 ORN 全部
BKPT 断点 BKPT 5
BL 带链接的跳转 B、BL、BX、BLX 和 BXJ 全部
BLX 带链接的跳转,更改指令集 B、BL、BX、BLX 和 BXJ T
BX 跳转,更改指令集 B、BL、BX、BLX 和 BXJ T
BXJ 跳转,更改为 Jazelle B、BL、BX、BLX 和 BXJ J,x7M
CBZ, CBNZ 比较,如果为(非)零,则跳转 CBZ 和 CBNZ T2
CDP 协处理器数据处理操作 CDP 和 CDP2 x6M
CDP2 协处理器数据处理操作 CDP 和 CDP2 5,x6M
CHKA 检查数组 CHKA EE
CLREX 清除独占 CLREX K,x6M
CLZ 计算前导零数目 CLZ 5,x6M
CMNCMP 与负值比较,比较 CMP 和 CMN 全部
CPS 更改处理器状态 CPS 6
DBG 调试 DBG、DMB、DSB 和 ISB 7
DMBDSB 数据内存屏障,数据同步屏障 DBG、DMB、DSB 和 ISB 7,6M
ENTERXLEAVEX 将状态更改为 ThumbEE 或更改状态 ThumbEE ENTERX 和 LEAVEX EE
EOR 异或 AND、ORR、EOR、BIC 和 ORN 全部

HBHBL

HBLPHBP

处理程序跳转,跳转到指定处理程序 HB、HBL、HBLP 和 HBP EE
ISB 指令同步屏障 DBG、DMB、DSB 和 ISB 7,6M
IT 条件判断 IT T2
LDC 加载协处理器 LDC、LDC2、STC 和 STC2 x6M
LDC2 加载协处理器 LDC、LDC2、STC 和 STC2 5,x6M
LDM 加载多个寄存器 LDM 和 STM 全部
LDR 加载寄存器指令 内存访问指令 全部
LDR 伪指令 加载寄存器伪指令 LDR 伪指令 全部
LDREX 独占加载寄存器 LDREX 和 STREX 6,x6M
LDREXBLDREXH 独占加载寄存器,半字 LDREX 和 STREX K,x6M
LDREXD 独占加载寄存器,双字 LDREX 和 STREX K,x7M
LSLLSR 逻辑左移,逻辑右移 ASR、LSL、LSR、ROR 和 RRX 全部
MAR 从寄存器移动到 40 位累加器 MAR 和 MRA XScale
MCR 从寄存器移动到协处理器 MCR、MCR2、MCRR 和 MCRR2 x6M
MCR2 从寄存器移动到协处理器 MCR、MCR2、MCRR 和 MCRR2 5,x6M
MCRR 从寄存器移动到协处理器 MCR、MCR2、MCRR 和 MCRR2 5E,x6M
MCRR2 从寄存器移动到协处理器 MCR、MCR2、MCRR 和 MCRR2 6,x6M

MIAMIAPH

MIAxy

带内部 40 位累加的乘法 MIA、MIAPH 和 MIAxy XScale
MLA 乘加 MUL、MLA 和 MLS x6M
MLS 乘减 MUL、MLA 和 MLS T2
MOV 移动 MOV 和 MVN 全部
MOVT 移动到顶部 MOVT T2
MOV32 伪指令 移动 32 位常数到寄存器 MOV32 伪指令 T2
MRA 从 40 位累加器移动到寄存器 MAR 和 MRA XScale
MRC 从协处理器移动到寄存器 MRC、MRC2、MRRC 和 MRRC2 全部
MRC2 从协处理器移动到寄存器 MRC、MRC2、MRRC 和 MRRC2 5,x6M
MRS 从 PSR 移动到寄存器 MRS 全部
MSR 从寄存器移动到 PSR MSR 全部
MUL 乘法 MUL、MLA 和 MLS 全部
MVN 取反移动 MOV 和 MVN 全部
NOP 无操作 NOP、SEV、WFE、WFI 和 YIELD 全部
ORN 逻辑“或非” AND、ORR、EOR、BIC 和 ORN T2
ORR 逻辑“或” AND、ORR、EOR、BIC 和 ORN 全部
PKHBTPKHTB 组合半字 PKHBT 和 PKHTB 6,x7M
PLD 预载数据 PLD、PLDW 和 PLI 5E,x6M
PLDW 预载要写入的数据 PLD、PLDW 和 PLI 7MP
PLI 预载指令 PLD、PLDW 和 PLI 7
PUSHPOP 将寄存器推入 (PUSH) 堆栈,从堆栈弹出 (POP) 寄存器 PUSH 和 POP 全部

QADDQDADD

QDSUBQSUB

饱和算法 QADD、QSUB、QDADD 和 QDSUB 5E,x7M

QADD8QADD16

QASXQSUB8

QSUB16QSAX

并行有符号饱和算法 并行加法和减法 6,x7M
RBIT 反转位 REV、REV16、REVSH 和 RBIT T2

REVREV16

REVSH

反转字节顺序 REV、REV16、REVSH 和 RBIT 6
RFE 从异常中返回 RFE T2,x7M
ROR 向右循环移寄存器 ASR、LSL、LSR、ROR 和 RRX 全部
RSB 反向减法 ADD、SUB、RSB、ADC、SBC 和 RSC 全部
RSC 带进位反向减法 ADD、SUB、RSB、ADC、SBC 和 RSC x6M

SADD8SADD16

SASX

并行有符号算法 并行加法和减法 6,x7M
SBC 带进位的减法 ADD、SUB、RSB、ADC、SBC 和 RSC 全部
SBFXUBFX 有符号、无符号位域提取 SBFX 和 UBFX T2
SDIV 有符号除法 SDIV 和 UDIV 7M,7R
SEL 根据 APSR GE 标记选择字节 SEL 6,x7M
SETEND 设置内存访问的端标记 SETEND 6,x7M
SEV 设置事件 NOP、SEV、WFE、WFI 和 YIELD K,6M

SHADD8SHADD16

SHASXSHSUB8

SHSUB16SHSAX

并行有符号均分算法 并行加法和减法 6,x7M
SMC 安全监控调用 SMC Z
SMLAD 两次有符号乘加 SMLAD 和 SMLSD 6,x7M
(32 <= 32 + 16 x 16 + 16 x 16)
SMLAL 有符号乘加 (64 <= 64 +32 x 32) UMULL、UMLAL、SMULL 和 SMLAL x6M
SMLALxy 有符号乘加 (64 <= 64 +16 x 16) SMLALxy 5E,x7M
SMLALD 两次有符号长整数乘加 SMLALD 和 SMLSLD 6,x7M
(64 <= 64 + 16 x 16 + 16 x 16)
SMLSD 两次有符号乘减累加 SMLAD 和 SMLSD 6,x7M
(32 <= 32 + 16 x 16 – 16 x 16)
SMLSLD 两次有符号长整数乘减累加 SMLALD 和 SMLSLD 6,x7M
(64 <= 64 + 16 x 16 – 16 x 16)
SMMUL 有符号高位字乘法 (32 <= TopWord(32 x 32)) SMMUL、SMMLA 和 SMMLS 6,x7M
SMUADSMUSD 有符号双乘法,并将乘积相加或相减 SMUAD{X} 和 SMUSD{X} 6,x7M
SMULxy 有符号乘法 (32 <= 16 x 16) SMULxy 和 SMLAxy 5E,x7M
SMULL 有符号乘法 (64 <= 32 x 32) UMULL、UMLAL、SMULL 和 SMLAL x6M
SMULWy 有符号乘法 (32 <= 32 x 16) SMULWy 和 SMLAWy 5E,x7M
SRS 存储返回状态 SRS T2,x7M
SSAT 有符号饱和 SSAT 和 USAT 6,x6M
SSAT16 有符号饱和,并行半字 SSAT16 和 USAT16 6,x7M

SSUB8SSUB16

SSAX

并行有符号算法 并行加法和减法 6,x7M
STC 存储协处理器 LDC、LDC2、STC 和 STC2 x6M
STC2 存储协处理器 LDC、LDC2、STC 和 STC2 5,x6M
STM 存储多个寄存器 LDM 和 STM 全部
STR 存储寄存器指令 内存访问指令 全部
STREX 独占存储寄存器 LDREX 和 STREX 6,x6M
STREXBSTREXH 独占存储寄存器,字节或半字 LDREX 和 STREX K,x6M
STREXD 独占存储寄存器,双字 LDREX 和 STREX K,x7M
SUB 减法 ADD、SUB、RSB、ADC、SBC 和 RSC 全部
SUBS pc, lr 从异常中返回,无出栈 SUBS pc, lr T2,x7M
SVC(以前为 SWI 超级用户调用 SVC 全部
SWPSWPB 交换寄存器和内存(仅 ARM) SWP 和 SWPB 所有,x7M

SXTB, SXTB16, 

SXTH

有符号扩展 SXT、SXTA、UXT 和 UXTA 6

SXTAB, SXTAB16, 

SXTAH

有符号扩展,带加法 SXT、SXTA、UXT 和 UXTA 6,x7M
TBBTBH 表跳转字节、半字 TBB 和 TBH T2
TEQTST 相等测试、测试 TST 和 TEQ 全部

UADD8UADD16

UASX

并行无符号算法 并行加法和减法 6,x7M
UDIV 无符号除法 SDIV 和 UDIV 7M,7R

UHADD8UHADD16

UHASXUHSUB8

UHSUB16UHSAX

并行无符号均分算法 并行加法和减法 6,x7M
UMAAL 无符号长整型乘加累加 UMAAL 6,x7M
(64 <= 32 + 32 + 32 x 32)
UMLALUMULL 无符号乘加,乘法 UMULL、UMLAL、SMULL 和 SMLAL x6M
(64 <= 32 x 32 + 64), (64 <= 32 x 32)

UQADD8UQADD16

UQASXUQSUB8

UQSUB16UQSAX

并行无符号饱和算法 并行加法和减法 6,x7M
USAD8 差值的绝对值无符号求和 USAD8 和 USADA8 6,x7M
USADA8 差值的绝对值无符号求和再累加 USAD8 和 USADA8 6,x7M
USAT 无符号饱和 SSAT 和 USAT 6,x6M
USAT16 无符号饱和,并行半字 SSAT16 和 USAT16 6,x7M

USUB8USUB16

USAX

并行无符号算法 并行加法和减法 6,x7M
UXTB, UXTB16, UXTH 无符号扩展 SXT、SXTA、UXT 和 UXTA 6
UXTAB, UXTAB16, UXTAH 无符号扩展,带加法 SXT、SXTA、UXT 和 UXTA 6,x7M
V* 请参阅Chapter 5 NEON 和 VFP 编程
WFEWFIYIELD 等待事件,等待中断,通知 NOP、SEV、WFE、WFI 和 YIELD T2,6M


   ========================================

Table 1.1 ARM ABI register usage
Register Brief Preserved Rules
r0 Argument and result No r0 and r1 are used for passing the first two arguments to functions, and returning the results of functions. If a function does not use them for a return value, they can take any value after a function.
r1 Argument and result No
r2 Argument No r2 and r3 are used for passing the second two arguments to functions. There values after a function is called can be anything.
r3 Argument No
r4 General purpose Yes r4 to r12 are used for working values, and their value after a function is called must be the same as before.
r5 General purpose Yes
r6 General purpose Yes
r7 General purpose Yes
r8 General purpose Yes
r9 General purpose Yes
r10 General purpose Yes
r11 General purpose Yes
r12 General purpose Yes
lr Return address No lr is the address to branch back to when a function is finished, but this does have to contain the same address after the function has finished.
sp Stack pointer Yes

sp is the stack pointer, described below. Its value must be the same after the function has finished.

========================================

movw 与 movt 指令

movw 与 movt 一般结合使用,用来往寄存器中加载一个 32 bit value。

环境:xcode 4.6.2,iPad 2, lldb

代码:

void ArmTest() {

    asm (

            "movw    r1, #0xF8C4\n\t" // 1

            "movt    r1, #0x40\n\t" // 2

            "mov     r0, r0" 

         );

}

在函数的开始部分设置断点,

然后读取 r1 寄存器的值(register read r1):r1 = 0x00000000

使用 ni 调试指令来继续执行一条指令,读取 r1 寄存器的值:r1 = 0x0000f8c4

继续单指令执行,读取寄存器值:r1 = 0x0040f8c4

可以得到结论:movw 将值加载到寄存器的低 16 位,movt 加载到高 16 位,合起来加载一个 32 bit value。

========================================

========================================

movs 说明

movs r3, #0

cpsr           {

  0x30,

  n = 0x0,

  z = 0x0,

  c = 0x0,

  v = 0x0,

  q = 0x0,

  j = 0x0,

  ge = 0x0,

  e = 0x0,

  a = 0x0,

  i = 0x0,

  f = 0x0,

  t = 0x1,

  mode = 0x10

}

执行后:

cpsr           {

  0x40000030,

  n = 0x0,

  z = 0x1,

  c = 0x0,

  v = 0x0,

  q = 0x0,

  j = 0x0,

  ge = 0x0,

  e = 0x0,

  a = 0x0,

  i = 0x0,

  f = 0x0,

  t = 0x1,

  mode = 0x10

}

总之,movs 在 mov 的功能基础上影响标志位(zero位)。

=============================

bic 指令

bic Rd,  Rn, Oprand2

BIC(位清除)指令对 Rn 中的值 和 Operand2 值的反码按位进行逻辑“与”运算。

BIC 是 逻辑”与非” 指令, 实现的 Bit Clear的功能

举例:

BIC     R0,   R0  , #0xF0000000

#将 R0  高4位清零

BIC    R1,  R1,   #0x0F

#将R1   低4位清0

RSB 反向减法

Rn, Operand2

RSB(反向减法)指令可从 Operand2 中的值减去 Rn 中的值。

这是很有用的,因为有了该指令,Operand2 的选项范围就会更大。

例如:

RSB r4, r4, #1280

从1280中减去 R4

RSB R4, R0, #0×46

从0×46 中 减去 R0, 放入R4

===================================

STM 与 LDM

STM和LDM的主要用途是现场保护、数据复制、参数传递等,其模式有8种,如下:

注:前面4种用于数据块的传输,后面4种用于堆栈操作

(1)IA  每次传送后地址加4

(2)IB  每次传送前地址加4

(3)DA  每次传送后地址减4

(4)DB  每次传送前地址减4

(5)FD  满递减堆栈

(6)FA  满递增堆栈

(7)ED  空递减堆栈

(8)EA  空递增堆栈

   下面的讲述对于空递减堆栈和空递增堆栈同样适用.

   在堆栈操作时,经常错误以为使用STMFD满递减将寄存器压入堆栈后,在弹出数据的时候应该使用LDMFA。

但是FD和FA仅用于指示目前操作的堆栈是何种模式(堆栈共有四种模式),FD指明目前的堆栈是满递减堆栈,

则数据入栈时的指令为STMFD,那么数据出栈时的指令对应的为LDMFD,而不是LDMFA。

   我们可以这样认为STMFD等价于STMDB,LDMFD等价于STMIA

   那么,数据传输的顺序和数据入栈的顺序又是如何呢

   先来看STMFD SP!,{R1-R3}  执行的结果图(操作之后SP指向SP')

                 SP-------> |R3|

                                 |R2|

                  SP'------>|R1|

那么STMFD SP!,{R3,R2,R1}执行后的堆栈顺序是不是刚好和上面的堆栈顺序相反,实际情况时这两个指令执行后的堆栈数据顺序一样,因为ARM编译器会自动将STMFD SP!,{R3,R2,R1}转换为STMFD SP!,{R0-R3}指令,也就是说,ARM编译器默认高寄存器优先存入堆栈。即便你在指令STMFD SP!,{R3,R2,R1}中刻意“安排”了寄存器入栈顺序,而在编译时编译器又重新做了处理,打乱了你期望的数据入栈顺序。

同理STMDB R0!,{R1-R3}和STMDB R0!,{R3,R2,R1}指令执行后数据在堆栈中的顺序完全一致。

STMFD SP!,{R1-R3}指令对应的出栈指令是LDMFD SP!,{R1-R3}(R1,R2,R3的顺序任意)

===================================

CBZ & CBNZ

比较,为零则跳转;比较,为非零则跳转。

语法

其中:

  • Rn

  • 是存放操作数的寄存器。

  • label

  • 是跳转目标。

用法

可以使用 CBZ 或 CBNZ 指令避免更改条件代码标记并减少指令数目。

除了不更改条件代码标记外,CBZ Rn, label 与下列指令序列功能相同:

除了不更改条件代码标记外,CBNZ Rn, label 与下列指令序列功能相同:

限制

跳转目标必须在指令之后的 4 到 130 个字节之内。

===================================

IT             EQ      /* if the EQ condition is true, (T)hen execute the next instruction */

MOVEQ   r0, #1  /* note the redundant condition code, which needs to match the IT instruction */

------------------

ITE           EQ      /* if the EQ condition is true, (T)hen execute the next instruction (E)lse execute the instruction after it */

MOVEQ   r0, #1

MOVNE   r0, #0  /* note that the condition code must be inverted, since this is an "else" instruction */

===================================

发表评论