如果不能正常显示,请查看原文 , 或返回

ARM备忘

mov: move

sub: subtract

cmp: compare

cmpls: ls--->lower or same, le--->less or equal, hi--->higher

ldr: load register

lsl: logical shift left

str: store register

b: branch

bl: branch label, change pc

bne: branch not equal

beq: branch equal

blt: branch less than

push {r4, r5} : store r4, r5 to stack

pop {r4, r5}: restore r4, r5 from stack

ldm: load multiple

stm: store multiple

and: 

ldrd r0, r1, [r2, #4] : load 8 bytes from r2 + 4, and high 4 bytes stored in r0,  lower in r1

.align 2:  2 * 2 = 4, the ldr instruction we used to read memory only works at addresses that are multiples of 4

tst : compares two numbers by computing the logical and operation of the numbers, and then comparing the result with 0 

strh reg,[dest]: stores the low half word number in reg at the address given by dest.

alias .req: reg sets alias to mean the register reg.

.unreq alias: removes the alias alias.

teq reg,#val: checks if the number in reg is equal to val.

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

Table 1.1 ARM ABI register usage
Register Brief Preserved Rules
r0Argument and resultNor0 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.
r1Argument and resultNo
r2ArgumentNor2 and r3 are used for passing the second two arguments to functions. There values after a function is called can be anything.
r3ArgumentNo
r4General purposeYesr4 to r12 are used for working values, and their value after a function is called must be the same as before.
r5General purposeYes
r6General purposeYes
r7General purposeYes
r8General purposeYes
r9General purposeYes
r10General purposeYes
r11General purposeYes
r12General purposeYes
lrReturn addressNolr 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.
spStack pointerYes

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。

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

	Register  	Alt. Name  	Usage
	r0 		a1 		First function argument Integer function result Scratch register
	r1 		a2 		Second function argument Scratch register
	r2 		a3 		Third function argument Scratch register
	r3 		a4 		Fourth function argument Scratch register

	r4 		v1 		Register variable
	r5 		v2 		Register variable
	r6 		v3 		Register variable
	r7 		v4 		Register variable
	r8 		v5 		Register variable
	r9 		v6
			rfp 		Register variable Real frame pointer

	r10 		sl 		Stack limit
	r11 		fp 		Argument pointer
	r12 		ip 		Temporary workspace
	r13 		sp 		Stack pointer
	r14 		lr 		Link register Workspace
	r15 		pc 		Program counter

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

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

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

语法

CBZ Rn, label
CBNZ Rn, label

其中:

Rn

是存放操作数的寄存器。

label

是跳转目标。

用法

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

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

    CMP     Rn, #0
    BEQ     label

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

    CMP     Rn, #0
    BNE     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 */

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

返回