登录站点

用户名

密码

常用ARM指令

已有 1611 次阅读  2009-09-11 15:58   标签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指令包含宏文件

 

 

 

 


 
最超值的ARM7/ARM9开发板系列
AVR单片机开发板与仿真器
 
本章节主要介绍ARM 处理器的基本程序设计方法,包含ARM 指令实验,Thumb 指令实验和ARM 处理器工作模式实验。

4.1 ARM 指令实验
4.1.1 实验说明
  实验目的:    透过实验掌握ARM 组译指令的使用方法。


         实验设备: 硬件使用PC 主机,软件使用Embest IDE 2003 整合开发环境,Windows 98/2000/NT/XP。

         实验内容:    使用简单ARM 组译指令,操作寄存器和内存区作互相的数据交换。

4.1.2 实验原理
ARM 处理器共有37个寄存器:31个通用寄存器,包括程序计数器(PC)。这些寄存器都是32 位的。6个状态寄存器。这些寄存器也是32 位的,但是只是使用了其中的12 位。

ARM 通用寄存器

通用寄存器(R0~R15)可分为3 类:

不分组寄存器R0~R7;

分组寄存器R8~R14;

程序计数器R15。

 

1)不分组寄存器R0~R7

R0~R7 是不分组寄存器。这意味着在所有处理器模式下,它们都存取一样的32 位寄存器。它们是真正的通用寄存器,没有架构所隐含的特殊用途。

 

2)分组寄存器R8~R14

R8~R14 是分组寄存器。它们存取的物理寄存器取决于当前的处理器模式。若要存取特定的物理寄存器而不依赖当前的处理器模式,则要使用规定的各字。

寄存器R8~R12 各有两组物理寄存器:一组为FIQ 模式,另一组为除了FIQ以外的所有模式。寄存器R8~R12 没有任何指定的特殊用途。只是使用R8~R14来简单地处理中断。寄存器R13,R14 各有6 个分组的物理寄存器。1 个用于用户模式和系统模式,其它5 个分别用于5 种异常模式。寄存器R13 通常用做堆迭指标,称为SP。每种异常模式都有自己的R13。寄存器R14 用作子程序链接寄存器,也称为LR。

 

3) 程序计数器R15

寄存器R15 用做程序计数器(PC)。程序状态寄存器在所有处理器模式下都可以存取当前的程序状态寄存器CPSR。CPSR 包含条件码标志位,中断禁止位,当前处理器模式以及其它状态和控制信息。每种异常模式都有一个程序状态保存寄存器SPSR。当例外出现时,SPSR 用于保留CPSR的状态。

CPSR 和SPSR 的格式如下:

31
 30
 29
 28
 27
 26         8
 7
 6
 5
 4
 3
 2
 1
 0
 
N
 Z
 C
 V
 Q
 DNM(RAZ)
 I
 F
 T
 M
 M
 M
 M
 M
 

 

条件码标志:N,Z,C,V 大多数指令可以测试这些条件码标志以决定程序指令如何执行

控制位:最低8 位I,F,T 和M 位用做控制位。当异常出现时改变控制位。当处理器在特权模式下也可以由软件改变。

中断禁止位:I 置1 则禁止IRQ 中断。F 置1 则禁止FIQ 中断。T 位:T=0 指示ARM 执行。T=1 指示Thumb 执行。在这些架构系统中,可自由地使用能在ARM 和Thumb 状态之间切换的指令。

模式位:M0, M1, M2, M3 和M4 (M[4:0]) 是模式位.这些位

决定处理器的工作模式.如表2-1 所示。

表4-1 ARM 工作模式M[4:0]

M[4:0]
 模式
 可存取的寄存器
 
0b10000
 用户模式
 PC, R14~R0,CPSR
 
0b10001
 FIQ模式
 PC, R14_fiq~R8_fiq,R7~R0,CPSR,SPSR_fiq
 
0b10010
 IRQ模式
 PC, R14_irq~R8_fiq,R12~R0,CPSR,SPSR_irq
 
0b10011
 管理模式
 PC, R14_svc~R8_svc,R12~R0,CPSR,SPSR_svc
 
0b10111
 中止
 PC, R14_abt~R8_abt,R12~R0,CPSR,SPSR_abt
 
0b11011
 未定义
 PC, R14_und~R8_und,R12~R0,CPSR,SPSR_und
 
0b11111
 系统
 PC, R14~R0,CPSR
 

其它位程序状态寄存器的其它位保留,用作以后的扩充。

 

4.1.3. 实验操作步骤
1. 执行ADS1.2开发环境,打开实验系统例程目录下ARMcode_test 子目录下的ARMcode.mcp 工程文件。

2. 透过操作菜单栏或使用快捷命令编译链接项目。

3. 选择Debug 菜单Remote Connect 进行连接软件仿真器,执行Download命令下载程序,并打开寄存器窗口。

4. 单步执行程序并观察和记录寄存器R0-R15 的值变化。

5. 结合实验内容和相关数据,观察程序执行,透过实验加深理解ARM指令的使用。

 

 

 

4.1.4  试验程序代码
;本程序将数据区从数据区SRC复制到目标数据区DST。复制时,以8个字节为单位进行。对于

;最后所剩不足的8个字节的数据,以字为单位进行复制,这时程序跳转到copywords处执行。

;在进行以8个字为单位的数据复制时,保存了所有的8个工作寄存器。

 

;设置本段程序的名称(Block)及属性

 AREA Block,CODE,READONLY

 

                    

;设置将要复制的字数(定义变量num,并赋值为20)

num EQU 20                

 

;程序入口标志

       ENTRY

start

 

;r0寄存器指向源数据区(SRC 标识的地址放入R0)

       LDR       r0,=src   

 

;r1寄存器指向目标数据区(DST 标识的地址放入R1)      

       LDR       r1,=dst   

      

;r2指定将要复制的字数(装载num 的值到R2)  

       MOV      r2, #num

             

;设置数据栈指针(R13),用于保存工作寄存器数值(设定SP堆栈开始地址为0x400)

       MOV      sp, #0x400

 

             

;进行以8个字节为单位的数据复制

blockcopy

 

;需要进行的以8个字为单位的复制次数( R2 右移3 位后的值放入R3)

       MOVS r3,r2, LSR #3    

;对于剩下的不足8个字的数据,跳转到copywords,以字为单位复制(判断是否为0,为0 跳移)

      

       BEQ copywords                  

;保存工作寄存器(把R4 到R11 的值保存到SP 标识的堆栈中)

       STMFD sp!, {r4-r11}         

 

octcopy

;从数据区读取8个字节的数据,放到8个寄存器中,并更新目标数据区指针r0(把R0 中的地址标识的内容顺序装载到R4 到R11 中)

 

       LDMIA r0!, {r4-r11}          

;将这8个字数据写入到目标数据区,并更新目标数据区指针r1(把R4 到R11 的值顺序保存到以R1 起始地址的内存中)

       STMIA r1!, {r4-r11}           

 

;将块的复制次数减1 (R3 -1 计数)

       SUBS r3, r3, #1                  

 

;循环,直到完成以8个字为单位的块复制

       BNE octcopy                      

 

;需要注意的是,LDMIA 或者STMIA 指令执行后,R0,R1 的值产生变化,每一次寄存器操作,R0 或者R1 的值会自动增加一个字节的量,这里操作了8 个寄存器,R0 或者R1 的值也相应增加了8 个字节

 

 

;恢复工作寄存器值(把刚才保存的SP 堆栈中的值恢复到R4 到R11 中)

       LDMFD sp!, {r4-r11}  

       

copywords

;剩下不足8个字的数据的字数(逻辑与,把R2 前7 位扔掉)

       ANDS r2, r2, #7          

 

;数据复制完成(判断是否为0,为0 跳移)

       BEQ stop                           

 

wordcopy

;从源数据区读取18个字的数据,放到r3寄存器中,并更新目标数据区指针r0(把R0 表示地址的内容的后4 位全部拷贝到R3)

       LDR r3, [r0], #4   

 

;将这r3中数据写入到目标数据区中,并更新目标数据区指针r1 (把R3 的内容,放入以R1 为起始地址的4 位内存中)      

       STR r3, [r1], #4           

      

;将字数减1;(R2 -1 放回R2)

       SUBS r2, r2, #1           

 

;循环,直到完成以字为单位的数据复制(判断是否为0,不为0 跳移,同样的,这里R0,R1 操作后,R0,R1 会自动加上便宜量)   

       BNE wordcopy                  

                                         

stop

;从应用程序中退出

       MOV      r0,   #0x18

       LDR       r1,   =0x20026

       SWI 0x123456

;定义数据区bloackdata

 

       AREA     Bloackdata,     DATA,    READWRITE

;定义源数据区src及目标数据区dst

src   DCD       1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4

dst   DCD       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

 

;结束汇编

       END

4.1.5 实验练习题
1. 撰写程序循环对R4~R11 进行8 次累加,R4~R11 起始值为1~8,每次加操作后把R4~R11 的内容放入SP 堆栈中,SP 初始设定为0x800。最后把R4~R11 用LDMFD 指令清空值为0。

2. 对于每一种ARM 的寻址方法,简短的写出相对的应用程序片段。

4.2 ARM 处理器工作模式实验
4.2.1. 实验说明
         实验目的:透过实验掌握ARM 处理器工作模式的切换。

         实验设备:软件需要ADS1.2开发环境,Windows 98/2000/NT/XP。

         实验内容:透过ARM 组译指令,在各种处理器模式下切换并观察各种模式下缓存器的区别;掌握ARM 不同模式的进入与退出。

4.2.2. 实验原理
ARM 处理器模式

ARM 架构支持下表2-2 所列的7 种处理器模式。

工作模式
 描述
 
用户模式(User,usr)
 正常程序执行的模式
 
快速中断模式(FIQ,fig)
 用于高速数据传输和数据处理
 
外部中断模式(IRQ,irq)
 用于通常的中断处理
 
特权模式(管理模式)(Supervisor,sve)
 共操作系统使用的一种模式
 
数据访问中止模式(Abort,abt)
 用于虚拟存储及存储保护
 
未定义指令中断模式(Undefind,und)
 用于支持通过软件方针的协处理器
 
系统模式(System,sys)
 用于运行特权的操作系统任务
 

 

 

大多数应用程序在用户模式下执行。当处理器工作在用户模式时,正在执行的程序不能存取某些被保护的系统资源,也不能改变模式,除非例外(exception)发生。这允许适当撰写操作系统来控制系统资源的使用。

除用户模式外的其它模式称未特权模式。它们可以自由的存取系统资源和改变模式。其中的5 种称为异常模式,即

n         FIQ(Fash Interrupt request);

n         IRQ(Interrupt ReQuest);

n         管理(Supervisor);

n         中止(Abort) ;

n         未定义(Underfined) 。

当特定的异常出现时,进入相应的模式。每种模式都有某些附加的寄存器,以避免异常出现时用户模式的状态不可靠。

剩下的模式是系统模式。仅ARM 架构V4 以及以上的版本有该模式。不能由于任何异常而进入该模式。它与用户模式有完全相同的寄存器。然而它是特权模式,不受用户模式的限制。它供需要存取系统资源的操作系统工作使用,单希望避免使用与例外模式有关的附加寄存器。避免使用附加寄存器保证了当任何异常出现时,都不会使工作的状态不可靠。

4.2.3. 实验操作步骤
1.开发环境,打开实验系统例程目录下ARMMode_test\ARMMode.MCP 项目,并编译链接项目。

3. 单步执行程序并观察和记录CPSP 和SPSR 缓存器值的变化;并观察在相应模式下执行程序后对应缓存器值的变化。

4. 结合实验内容和相关数据,观察程序执行,透过实验加深理解和掌握

4.2.4  试验程序代码
;设置本段程序的名称(Block)及属性

 AREA Block,CODE,READONLY

 

;程序入口标志

       ENTRY

start

 

       B     Reset_Handler

      

Undefined_Handler

       B Undefined_Handler

       B SWI_Handler

      

Prefetch_Handler

       B Prefetch_Handler

      

Abort_Handler

       B Abort_Handler

       NOP ;空操作

      

IRQ_Handler

       B IRQ_Handler

      

FIQ_Handler

       B FIQ_Handler

      

SWI_Handler

       mov pc, lr

;前面部分是处理程序,主要处理各种模式的入端口跳移

 

Reset_Handler

 

;into System mode

       MRS R0,CPSR      ;复制CPSR 到R0

       BIC R0,R0,#0x1F ;清除R0 的后5 位

       ORR R0,R0,#0x1F       ;设定R0 的最后5 位为11111

       MSR       CPSR_c,R0    ;把R0 装载到CPSR,切换到系统模式

       MOV R0, #1         ;对系统模式下的R0 赋值,下面的R1~R15 一样

       MOV R1, #2

       MOV R2, #3

       MOV R3, #4

       MOV R4, #5

       MOV R5, #6

       MOV R6, #7

       MOV R7, #8

       MOV R8, #9

       MOV R9, #10

       MOV R10, #11

       MOV R11, #12

       MOV R12, #13

       MOV R13, #14

       MOV R14, #15

;into FIQ mode

       MRS R0,CPSR

       BIC R0,R0,#0x1F

       ORR R0,R0,#0x11 ;设定R0 的最后5 位为10001

       MSR CPSR_c,R0 ;把R0 装载到CPSR,切换到Fiq 模式

       MOV R8, #16 ;给Fiq 模式的特有缓存器R8 赋值, 下面的R9~R14 一样

       MOV R9, #17

       MOV R10, #18     

       MOV R11, #19

       MOV R12, #20

       MOV R13, #21

       MOV R14, #22

;into SVC mode

       MRS R0,CPSR

       BIC R0,R0,#0x1F

       ORR R0,R0,#0x13 ;设定R0 的最后5 位为10011

       MSR CPSR_c,R0   ;把R0 装载到CPSR,切换到Svc 模式

       MOV R13, #23      ;给SVC 模式的特有缓存器R13 赋值, 下面的R14 一样

       MOV R14, #24

;into Abort mode

       MRS R0,CPSR

       BIC R0,R0,#0x1F

       ORR R0,R0,#0x17 ;设定R0 的最后5 位为10111

       MSR CPSR_c,R0 ;把R0 装载到CPSR,切换到Abort 模式

       MOV R13, #25 ;给Abort 模式的特有缓存器R13 赋值, 下面的R14 一样

       MOV R14, #26

;into IRQ mode

       MRS R0,CPSR

       BIC R0,R0,#0x1F

       ORR R0,R0,#0x12 ;设定R0 的最后5 位为10010

       MSR CPSR_c,R0 ;把R0 装载到CPSR,切换到IRQ 模式

       MOV R13, #27 ;给IRQ 模式的特有缓存器R13 赋值, 下面的R14一样

       MOV R14, #28

;into UNDEF mode

       MRS R0,CPSR

       BIC R0,R0,#0x1F

       ORR R0,R0,#0x1b        ;设定R0 的最后5 位为11011

       MSR CPSR_c,R0                 ;把R0 装载到CPSR,切换到UNDEF 模式

       MOV R13, #29             ;给UNDEF 模式的特有缓存器R13 赋值, 下面的R14 一样

       MOV R14, #30

       B Reset_Handler ;跳移到最开始地方循环

       END

4.2.5. 实验练习题
1. 参考例子,把其中系统模式程序更改为使用者模式程序,编译除错,观察执行结果,检查是否正确,如果有有错误分析其原因。(提示:不能从使用者模式直接切换到其它模式,可以先使用SWI 指令切换到管理模式)。

上一篇: verilog设计经验点滴 下一篇: 山东大学嵌入式系统原理与接口技术课程试卷(A)

分享 举报