常用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             ; r2+4作为指针,指向的值存入r1,并且r2=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指令包含宏文件

posted @ 2015-02-10 13:53  天道酬勤的鱼  阅读(208)  评论(0)    收藏  举报