原创 汇编常用命令

2009-3-22 12:39 3316 4 4 分类: MCU/ 嵌入式

当处理器工作在ARM状态时,几乎所有的指令均根据CPSR中条件码的状态和指令的条件域有条件的执行。当指令的执行条件满足时,指令被执行,否则指令被忽略。
每一条ARM指令包含4位的条件码,位于指令的最高4[31:28]。条件码共有16种,每种条件码可用两个字符表示,这两个字符可以添加在指令助记符的后面和指令同时使用。例如,跳转指令B可以加上后缀EQ变为BEQ表示相等则跳转,即当CPSR中的Z标志置位时发生跳转。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


1 B指令
B
指令的格式为:
B{
条件} 目标地址
B
指令是最简单的跳转指令。一旦遇到一个 B 指令,ARM 处理器将立即跳转到给定的目标地址,从那里继续执行。注意存储在跳转指令中的实际值是相对当前PC值的一个偏移量,而不是一个绝对地址,它的值由汇编器来计算(参考寻址方式中的相对寻址)。它是 24 位有符号数,左移两位后有符号扩展为 32 位,表示的有效偏移为 26 (前后32MB的地址空间)。以下指令:
B Label
;程序无条件跳转到标号Label处执行
CMP R1
,#0 ;当CPSR寄存器中的Z条件码置位时,程序跳转到标号Label处执行
BEQ Label


<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />3.3.6 批量数据加载/存储指令
ARM
微处理器所支持批量数据加载/存储指令可以一次在一片连续的存储器单元和多个寄存器之间传送数据,批量加载指令用于将一片连续的存储器中的数据传送到多个寄存器,批量数据存储指令则完成相反的操作。常用的加载存储指令如下:
— LDM
批量数据加载指令
— STM
批量数据存储指令
LDM
(或STM)指令
LDM
(或STM)指令的格式为:
LDM
(或STM{条件}{类型} 基址寄存器{},寄存器列表{}
LDM
(或STM)指令用于从由基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个寄存器之间传送数据,该指令的常见用途是将多个寄存器的内容入栈或出栈。其中,{类型}为以下几种情况:
IA
每次传送后地址加1
IB
每次传送前地址加1
DA
每次传送后地址减1
DB
每次传送前地址减1
FD
满递减堆栈;
ED
空递减堆栈;
FA
满递增堆栈;
EA
空递增堆栈;
{
}为可选后缀,若选用该后缀,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。
基址寄存器不允许为R15,寄存器列表可以为R0R15的任意组合。
{
}为可选后缀,当指令为LDM且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据传送之外,还将SPSR复制到CPSR。同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。
指令示例:
STMFD R13!
{R0R4-R12LR} ;将寄存器列表中的寄存器(R0R4R12LR)存入堆栈。
LDMFD R13!
{R0R4-R12PC} ;将堆栈内容恢复到寄存器(R0R4R12LR)。


常用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
:基本指令,如LDRSTR
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”labeladdr1 = 当前地址
        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~r12lr寄存器的值到堆栈并更新堆栈指针。
        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
不同于LDRSTR指令,该指令可以寄存器间赋值


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中返回
【使用本地labellocal label)】
       
本地label可以在一个程序段内多次使用,用数字作为label的名称,也可以在数字后面跟一些字母。引用本地label的语法是:        %{F|B}{A|T}n{routname},其中F代表向前搜索本地labelB代表向后搜索,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,
NV相同                        >
LE                 Z = 1,
NV不同                 <=
例子:
                cmp                r0,                r1                ;
比较r0r1
                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             ;       
比较r28
                movlt        r0,                #2          ;
如果r2<8r0 = 2
       
ARM
汇编程序结构
;――――――――――――――――――――
AREA  EX2,  CODE,  READONLY
;AREA
指令定义一个程序段,名称为EX2,属性为:CODEREADONLY
        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,运行完后r0r1的值交换了
一般可以把宏写在宏文件(.mac文件)中,在程序里用INCLUDE指令包含宏文件


 
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
4
关闭 站长推荐上一条 /4 下一条