常用ARM指令

4520阅读 0评论2009-08-26 jimylion
分类:LINUX

常用ARM指令

1、 内存访问指令

基本指令:

LDR:memory -> register (memory包括映射到内存空间的非通用寄存器)

STR:register -> memory

语法:

  op{cond }{B}{T} Rd , [Rn ]

op{cond }{B} Rd , [Rn , FlexOffset ]{!}

op{cond }{B} Rd , label

op{cond }{B}{T} Rd , [Rn ], FlexOffset

op:基本指令,如LDR、STR

cond:条件执行后缀

B:字节操作后缀

T:用户指令后缀

Rd:源寄存器,对于LDR指令,Rd将保存从memory中读取的数值;对于STR指令,Rd保存着将写入memory的数值

Rn:指针寄存器

FlexOffset:偏移量

例子:

ldr r0, [r1] ;r1作为指针,该指针指向的数存入r0

str r0, [r1, #4] ;r1+4作为指针,r0的值存入该地址

str r0, [r1, #4]! ;同上,并且r1 = r1 + 4

ldr r1, =0x08100000 ;立即数0x08100000存到r1

ldr r1, [r2], #4 ; 

【label的使用】

addr1 ;定义一个名为“addr1”的label,addr1 = 当前地址

  dcd 0 ;在当前地址出定义一个32bit的变量

~ ~ ~

  ldr r1, label1 ;r1 = addr1,r1即可以作为var1的指针

  ldr r0, [r1]

  add r0, r0, #1

  str r0, [r1] ;变量var1的值加1

【FlexOffset的使用】

  FlexOffset可以是立即数,也可以是寄存器,还可以是简单的表达式

   

2、 多字节存取指令(常用于堆栈操作)

基本指令:

  LDM:memory ――> 多个寄存器

  STM:多个寄存器 ――> memory

语法:

  op{cond }mode Rn{!}, reglist {^}

  mode:指针更新模式,对应于不同类型的栈。最常用的是“FD”模式,相当于初始栈指针在高位,压栈后指针值减小。

  Rn:指针寄存器

  !:最后的指针值将写入Rn中

  reglist:要操作的寄存器列表,如{r0-r8, r10}

  ^ :完成存取操作后从异常模式下返回

例子:

;异常处理程序:

  sub lr, lr, #4 ; lr – 4是异常处理完后应该返回的地方

;保存r0~r12和lr寄存器的值到堆栈并更新堆栈指针。

  stmfd sp!, {r0-r12, lr} ;异常处理

  ldmfd sp!, {r0-r12, pc}^ ;从堆栈中恢复r0~r12,返回地址赋给pc指针,使程序返回到异常发生前所执行的地方,^标记用来使CPU退出异常模式,进入普通状态。



3、 算术运算指令

基本指令:

  ADD:加

  SUB:减

语法:

  op{cond }{S} Rd, Rn, Operand2

  S:是否设置状态寄存器(CPSR),如:N(有符号运算结果得负数)、Z(结果得0)、C(运算的进位或移位)、V(有符号数的溢出)等等。

  Rd:保存结果的寄存器

  Rn:运算的第一个操作数

  Operand2:运算的第二个操作数,这个操作数的值有一些限定:如可以是8位立即数(例:0xa8)或一个8为立即数的移位(例:0xa800,而0xa801就不符合)。也可以是寄存器,或寄存器的移位(如“r2, lsl #4”)。

例子:

  add r0, r1, r2 ; r0 = r1 + r2

  adds r0, r1, #0x80 ; r0 = r1 + 0x80,并设置状态寄存器

  subs r0, r1, #2000 ; r0 = r1 – 2000,并设置状态寄存器


4、 逻辑运算指令

基本指令:

  AND:与

  ORR:或

  EOR:异或

  BIC:位清0

语法:

  op{cond }{S} Rd, Rn, Operand2

  语法类似算术运算指令

例子:

  ands r0, r1, #0xff00 ; r0 = r1 and 0xff00,并设置状态寄存器

  orr r0, r1, r2 ; r0 = r1 and r2

  bics r0, r1, #0xff00 ; r0 = r1 and ! (0xff00)

  ands r0, r1, #0xffff00ff ; 错误


5、 MOV指令

语法:

MOV{cond}{S} Rd, Operand2

例子:

  mov r0, #8 ; r0 = 8

  mov r0, r1 ; r0 = r1

不同于LDR、STR指令,该指令可以寄存器间赋值


6、 比较指令

基本指令:

  CMP:比较两个操作数,并设置状态寄存器

语法:

  CMP{cond } Rn, Operand2

例子:

  cmp r0, r1 ; 计算r0 – r1,并设置状态寄存器,由状态寄存器可以知r0是否大于、小于或等于r1

  cmp r0, #0 ; 


7、 跳转指令

基本指令:

  B:跳转

  BL:跳转并将下一指令的地址存入lr寄存器

语法:

  op{cond} label

  label:要跳向的地址

例子:

loop1

  b loop1 ; 跳到地址loop1处

  bl sub1 ; 将下一指令地址写入lr,并跳至sub1

sub1

  mov pc, lr ; 从sub1中返回

【使用本地label(local label)】

  本地label可以在一个程序段内多次使用,用数字作为label的名称,也可以在数字后面跟一些字母。引用本地label的语法是: %{F|B}{A|T}n{routname},其中F代表向前搜索本地label,B代表向后搜索,A/T不常使用。

例子

100 ; 定义本地label,名称为“100”

~ ~ ~

100 ; 第二次定义本地label,名称为“100”

  ~ ~ ~

b %f100 ; 向前跳到最近的“100”处

~ ~ ~

b %b100 ; 向后跳至最近的“100”处

100 ; 第三次定义本地label 100


8、 条件执行

条件:状态寄存器中某一或某几个比特的值代表条件,对应不同的条件后缀cond,如:

后缀 (cond) 状态寄存器中的标记 意义

EQ Z =1 相等

NE Z = 0 不相等

GE N和V相同 >=

LT N和V不同 <

GT Z = 0, 且N和V相同 >

LE Z = 1, 或N和V不同 <=

例子:

  cmp r0, r1 ;比较r0和r1

  blgt sub1 ;如果r0>r1,跳转到sub1,否则不操作

  ;一段循环代码

  ldr r2, =8 ;r2 = 8

  loop

  ;这里可以进行一些循环内的操作

  subs r2, r2, #1 ;r2 = r2 –1,并设置状态位

  bne loop ;如果r2不等于0,则继续循环

;――――――――――――――――――――

  mov r0, #1 ; r0 = 1

  cmp r2, #8 ; 比较r2和8

  movlt r0, #2 ; 如果r2<8,r0 = 2


ARM汇编程序结构

;――――――――――――――――――――

AREA EX2, CODE, READONLY

;AREA指令定义一个程序段,名称为EX2,属性为:CODE、READONLY

  INCLUDE Common.inc ;包含汇编头文件

  IMPORT sub1 ;引用外部符号

  EXPORT prog1 ;向外输出符号

ENTRY ;ENTRY指令定义程序的开始

start ;此处定义了一个label start

MOV r0, #10  

MOV r1, #3

ADD r0, r0, r1 ;r0 =r0 +r1

prog1 ;此处定义了一个label prog1

MOV r0, #0x18  

LDR r1, =0x20026  

SWI 0x123456  

END ;END指令表示程序段的结束

;――――――――――――――――――――

宏的使用

定义宏:

MACRO ;宏的起始

{label} macroname para1,para2……

;代码

MEND ;宏结束

引用宏:

  marconame para1,para2……

例子

;定义一个宏,完成两个寄存器内容交换

  MACRO 

  swap $w1, $w2, $w3

  mov $w3, $w1

  mov $w1, $w2

  mov $w2, $w3

  MEND


;使用这个宏

ldr r0, =1

ldr r1, =2

swap r0, r1, r2 ;此处调用了宏swap,运行完后r0、r1的值交换了

一般可以把宏写在宏文件(.mac文件)中,在程序里用INCLUDE指令包含宏文件


上一篇:成大事者不拘小节
下一篇:[分享职业培训力显“学士后”就业优势