第3章 ARM9指令系统_第1页
第3章 ARM9指令系统_第2页
第3章 ARM9指令系统_第3页
第3章 ARM9指令系统_第4页
第3章 ARM9指令系统_第5页
已阅读5页,还剩157页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第三章ARM9指令系统1ARM9指令集,包括ARM指令集Thumb指令集。ARM微处理器的指令集是加载/存储型的.即指令集仅能处理寄存器中的数据,处理结果仍要放回寄存器中,而对系统存储器的访问则需要通过专门的加载/存储指令来完成。3.1ARM指令集23.1ARM指令集33.1ARM指令集4ARM指令的助记符

ARM指令在汇编程序中用助记符表示,一般ARM指令的助记符格式为:

<opcode>{<cond>}{S}<Rd>,<Rn>{,<op2>}例:ADDEQSR1,R2,#5操作码决定指令执行的条件域决定指令执行是否影响CPSR寄存器的值第一个操作数,为寄存器目的寄存器第二个操作数其中操作码opcode为ADD,条件域cond为EQ,表示该指令只有当CPSR中Z标志置位时才执行,目的寄存器Rd为R1,第一个操作数寄存器Rn为R2,第二个操作数op2为5;执行的结果为R1=R2+5,S表示将影响CPSR寄存器的值。43.1ARM指令集实际指令语法格式为:

ADDEQSR0,R1,R2;其中操作码opcode为ADD,条件域cond为EQ,表示该指令只有当CPSR中Z标志置位时才执行,目的寄存器Rd为R0,第一个操作数寄存器Rn为R1,第二个操作数op2为R12;执行的结果为R0=R1+R2,S表示将影响CPSR寄存器的值。该指令的编码格式为:31~2827~2524~212019~1615~1211~~~~~~~~~~0cond

opcodeSRnRdop2000000101001000100000000000000105条件域当处理器工作在ARM状态时,几乎所有的指令均根据CPSR中条件标志位的状态和指令的条件域有条件的执行。当指令的执行条件满足时,指令被执行,否则指令被忽略。每一条ARM指令包含4位的条件码,位于指令的最高4位[31:28]。条件码共有16种,每种条件码可用两个字符表示,这两个字符可以添加在指令助记符的后面和指令同时使用。例如:跳转指令B可以加上后缀EQ变为BEQ表示“相等则跳转”,即当CPSR中的Z标志置位时发生跳转。在16种条件标志码中,只有15种可以使用。6条件码条件码助记符后缀标志含义0000EQZ置位相等0001NEZ清零不相等0010CSC置位无符号数大于或等于0011CCC清零无符号数小于0100MIN置位负数0101PLN清零正数或零0110VSV置位溢出0111VCV清零未溢出1000HIC置位Z清零无符号数大于1001LSC清零Z置位无符号数小于或等于1010GEN等于V带符号数大于或等于1011LTN不等于V带符号数小于1100GTZ清零且(N等于V)带符号数大于1101LEZ置位或(N不等于V)带符号数小于或等于1110AL忽略无条件执行7C代码:if(a>b)a++;elseb++;对应的汇编代码:CMP R0,R1;R0与R1比较ADDHIR0,R0,#1;若R0>R1,则R0=R0+1ADDLSR1,R1,#1;若R0≤R1,则R1=R1+1示例:条件码83.1.1寄存器装载及存储指令9Load/Store指令用于寄存器和内存间数据的传送.Load用于把内存中的数据装载到寄存器中Store则用于把寄存器中的数据存入内存。

Load/Store指令分为三类:(1)单一数据传送指令(LDR和STR等)(2)多数据传送指令(LDM和STM)(3)数据交换指令(SWP和SWPB)

存储器寄存器(R0-R15)ARM微处理器外围模块或芯片存储加载1、单一数据加载/存储指令LDR和STR——字:32位字加载寄存器(LDR)和存储寄存器(STR)指令。LDR和STR指令都有以下4种句法形式:op{cond}Rd,[Rn] 零偏移op{cond}Rd,[Rn,Flexoffset]{!}前索引偏移op{cond}Rd,label

程序相对偏移op{cond}Rd,[Rn],Flexoffset

后索引偏移label程序相对偏移表达式。偏移量必须是在当前指令的上下4KB范围内。!可选后缀。若有“!”,则将包含偏移量的地址写回到Rn,若Rn是R15,则不能使用该后缀。后面所用时意义相同。{}表示括号内的内容是可选的。后面所用时意义相同。101、单一数据加载/存储指令Flexoffset

加到Rn上的灵活偏移量。该偏移量可以是下面两种形式之一:①#expr

是取值范围为-4095~+4095的整数,经常是常量或常量表达式。②{-}Rm{,shift}Rm是内含偏移量的寄存器,它不能是R15。shift是Rm的可选移位方法,可以是下列形式中的一种。ASRn算术右移n位(1≤n≤32);LSLn逻辑左移n位(0≤n≤31);LSRn逻辑右移n位(1≤n≤32);RORn循环右移n位(1≤n≤31);RRX循环右移1位,带扩展。111、单一数据加载/存储指令(1)LDR指令 格式为:

LDR{条件}目的寄存器,<存储器地址> LDR指令是字加载指令,用于从存储器中将一个32位的字数据传送到目的寄存器中。120x55R3R40x400000000x123456780x40000000存储器地址应用示例:LDR R3,[R4];将R4指向地址的字数据存入R30x12345678示例13示例指令示例:LDR R3,[R4]

;将存储器地址为R4的字数据读入寄存器R3。LDR R3,[R1,R2]

;将存储器地址为R1+R2的字数据读入寄存器R3。LDR R3,[R1,#8]

;将存储器地址为R1+8的字数据读入寄存器R3。LDR R3,[R1,R2]!

;将存储器地址为R1+R2的字数据读入寄存器R3,并将新地址R1+R2写入R1。LDR R3,[R1,#8]!;将存储器地址为R1+8的字数据读入寄存器R3,并将新地址R1+8写入R1。14示例LDR R3,[R1],R2

;将存储器地址为R1的字数据读入寄存器R3,并将新地址R1+R2写入R1。LDR R3,[R1,R2,LSL#3]!

;将存储器地址为R1+R2×8的字数据读入寄存器R3,并将新地址R1+R2×8写入R1。LDR R3,[R1],R2,LSL#3 ;将存储器地址为R1的字数据读入寄存器R3,并将新地址R1+R2×8写入R1。注:R15不可以作为偏移寄存器使用。151、单一数据加载/存储指令(2)STR指令 格式为:

STR{条件}源寄存器,<存储器地址>STR指令是字存储指令,用于从源寄存器中将一个32位的字数据传送到存储器中。使用方式可参考指令LDR。161、单一数据加载/存储指令指令示例:

STR R3,[R1],#8

;将R3中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。

STR R3,[R1,#8]

;将R3中的字数据写入以R1+8为地址的存储器中。178B/16B/双字的操作单一数据加载/存储指令还可以完成带符号和无符号的8位字节,带符号和无符号的16位半字以及双字操作。对于带符号加载时是带符号扩展到32位,无符号加载时是用“0”扩展到32位。该组LDR和STR指令也都有以下4种句法形式:Op{cond}typeRd,[Rn] 零偏移op{cond}typeRd,[Rn,offset]{!} 前索引偏移Op{cond}typeRd,label

程序相对偏移Op{cond}typeRd,[Rn],offset

后索引偏移18其中:type必须是下面所列的形式之一:H无符号半字;SH带符号半字(仅对LDR);B无符号字节;SB带符号字节(仅对LDR);D双字;19例如LDRHR1,[R0,#22];R1←[R0+22],加载16位半字,0扩展到32位LDREQSHR11,[R6];R11←[R6],加载16位半字,带符号扩展到32位STRHR4,[R0,R1]!;R4→[R0+R1],存储最低的有效半到R0+R1所指的地址开始的两个字节处,地址写回R0LDRDR6,[R11];R6←[R11],R7←[R11+4]STRDR4,[R9,#24];R4→[R9+24],R5→[R9+28]201、单一数据加载/存储指令(3)LDRB指令格式为: LDR{条件}B目的寄存器,<存储器地址> LDRB指令是字节加载指令,用于从存储器中将一个8位的字节数据传送到目的寄存器中,同时将寄存器的高24位清零。211、单一数据加载/存储指令指令示例:LDRBR3,[R1]

;将存储器地址为R1的字节数据读入寄存器R0,并将R3的高24位清零。LDRBR3,[R1,#8]

;将存储器地址为R1+8的字节数据读入寄存器R3,并将R3的高24位清零。221、单一数据加载/存储指令(4)LDRH指令 格式为:

LDR{条件}H目的寄存器,<存储器地址> LDRH指令是无符号半字加载指令,用于从存储器中将一个16位的半字数据传送到目的寄存器中,同时将寄存器的高16位清零。231、单一数据加载/存储指令指令示例:LDRHR3,[R1];将存储器地址为R1的半字数据读入寄存器R3,并将R3的高16位清零。LDRHR3,[R1,#8];将存储器地址为R1+8的半字数据读入寄存器R3,并将R3的高16位清零。LDRHR3,[R1,R2]

;将存储器地址为R1+R2的半字数据读入寄存器R3,并将R3的高16位清零。241、单一数据加载/存储指令(5)LDRSB有符号的字节数据加载指令格式:LDR{<cond>}SB<Rd>,<addr>功能:同LDRB指令,但该指令将寄存器Rd的高24位设置成所装载的字节数据符号位的值。例如:LDRSBR0,[R1];将内存中起始地址为R1的一个字节数据装入R0中,R0的高24位设置成该字节数据的符号位251、单一数据加载/存储指令(6)LDRSH有符号的半字数据加载指令格式:LDR{<cond>}SH<Rd>,<addr>功能:同LDRH指令,但该指令将寄存器Rd的高16位设置成所装载的半字数据符号位的值。例如:LDRSHR0,[R1];将内存中起始地址为R1的一个16位半字数据装入R0中,R0的高16位设置成该半字数据的符号位261、单一数据加载/存储指令(7)STRB指令 格式为:

STR{条件}B源寄存器,<存储器地址> STRB指令是无符号字节存储指令,用于从源寄存器中将一个8位的字节数据传送到存储器中。该字节数据为源寄存器中的低8位。271、单一数据加载/存储指令指令示例:STRBR3,[R1]

;将寄存器R3中的字节数据写入以R1为地址的存储器中。STRBR3,[R1,#8];将寄存器R3中的字节数据写入以R1+8为地址的存储器中。281、单一数据加载/存储指令(8)STRH指令格式为:

STR{条件}H源寄存器,<存储器地址>STRH指令是无符号半字存储指令,用于从源寄存器中将一个16位的半字数据传送到存储器中。该半字数据为源寄存器中的低16位。291、单一数据加载/存储指令指令示例:STRHR3,[R1]

;将寄存器R3中的半字数据写入以R1为地址的存储器中。STRHR3,[R1,#8];将寄存器R3中的半字数据写入以R1+8为地址的存储器中。302.多数据加载/存储指令(LDM和STM) ARM微处理器所支持批量数据加载/存储指令可以一次在一片连续的存储器单元和多个寄存器之间传送数据。批量加载指令用于将一片连续的存储器中的数据传送到多个寄存器,批量数据存储指令则完成相反的操作。312.多数据加载/存储指令(LDM和STM)常用的加载存储指令如下:LDM(或STM)指令格式为:LDM(或STM){条件}{类型}基址寄存器{!},寄存器列表{∧}

LDM(或STM)指令用于从由基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个寄存器之间传送数据,该指令的常见用途是将多个寄存器的内容入栈或出栈。!为可选后缀,若选用该后缀,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。∧为可选后缀,这是一个只是在数据块传送中使用的后缀,不允许在用户模式或系统模式下使用。当指令为LDM且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据传送之外,还将SPSR复制到CPSR。同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。基址寄存器不允许为R15。寄存器列表可以为R0~R15的任意组合,若使用连续的寄存器时,可以使用“-”表示省略。322.多数据加载/存储指令(LDM和STM)其中,{类型}为以下几种情况:IA 每次传送后地址加1,递增方式;IB 每次传送前地址加1,递增方式;DA 每次传送后地址减1,递减方式;DB 每次传送前地址减1,递减方式;FD 满递减堆栈;ED 空递减堆栈;FA 满递增堆栈;EA 空递增堆栈;333.2.3ARM存储器访问指令STMIB

R0!,{R1,R2,R3}指令执行前指令执行后R0R3R2R1R0STMIAR0!,{R1,R2,R3}指令执行前指令执行后R0R3R2R1R0地址增STMDAR0!,{R1,R2,R3}指令执行前指令执行后R0R3R2R1R0STMDBR0!,{R1,R2,R3}指令执行前指令执行后R0R3R2R1R0地址减342.多数据加载/存储指令(LDM和STM)例如

LDMIA/IB/DA/DBR13!,{R0-R1,R3};各指令执行完后,结果如图所示。IBDADB352.多数据加载/存储指令(LDM和STM)FD、ED、FA和EA指定是满栈还是空栈,是升序栈还是降序栈,用于堆栈寻址。一个满栈的栈指针指向上次写的最后一个数据单元.空栈的栈指针指向第一个空闲单元。一个降序栈是在内存中反向增长而升序栈在内存中正向增长。362.多数据加载/存储指令(LDM和STM)指令示例:STMFDR13!,{R0,R4-R12,LR}

;将寄存器列表中的寄存器(R0,R4到R12,LR)存入堆栈。.......LDMFDR13!,{R0,R4-R12,PC}

;将堆栈内容恢复到寄存器(R0,R4到R12,PC)。373.交换指令(SWP)格式为:SWP{条件}Rd,Rm,[Rn]SWP指令是数据字交换指令,用于将源寄存器Rn所指向的存储器中的字数据传送到目的寄存器中,同时将源寄存器Rm中的字数据传送到源寄存器Rn所指向的存储器中。

Rd=[Rn],[Rn]=Rm

当源寄存器Rm和目的寄存器为同一个寄存器时,指令交换该寄存器和存储器的内容。383.交换指令(SWP)指令示例:SWPR1,R2,[R3]

;将R3所指向的存储器中的字数据传送到R1,同时;将R2中的字数据传送到R3所指向的存储单元。SWPEQ R1,R1,[R2]

;Z=1时,完成将R2所指向的存储器中的字数据与;R1中的字数据交换。393.交换指令(SWP)SWPB指令格式为:SWP{条件}B

目的寄存器,源寄存器1,[源寄存器2]

SWPB指令是字节交换指令,用于将源寄存器2所指向的存储器中的字节数据传送到目的寄存器中,目的寄存器的高24位清零,同时将源寄存器1中的字节数据传送到源寄存器2所指向的存储器中。403.交换指令(SWP)指令示例:SWPBR1,R2,[R3];将R3所指向的存储器中的字节数据传送到R1,R1的高24位清零,同时将R2中的低8位数据传送到R3所指向的存储单元。SWPBR1,R1,[R2];该指令完成将R2所指向的存储器中的字节数据与R1中的低8位数据交换。413.1.2算术和逻辑指令算术和逻辑指令只能对寄存器的内容进行操作,不允许对存储器中的数据进行操作,也不允许指令直接使用存储器的数据或在寄存器与存储器之间传送数据。算术和逻辑指令可分为3大类:数据传送指令算术逻辑运算指令比较指令423.1.2算术和逻辑指令数据传送指令用于在寄存器和寄存器之间进行数据的传输。算术逻辑运算指令完成常用的算术与逻辑的运算,该类指令不但将运算结果保存在目的寄存器中,同时更新CPSR中的相应条件标志位。比较指令是完成对指定的两个寄存器(或1个寄存器,1个立即数)进行比较,不保存运算结果,只影响CPSR中相应的条件标志位。431.算术指令(1)ADD,SUB,RSB,ADC,SBC和RSC指令加、减和反减指令,前三个不带进位或借位,后三个带进位或借位。其句法是:op{cond}{S}Rd,Op1,Op2441.算术指令-ADDADD加法指令(Addition)ADD{<cond>}{S}<Rd>,<op1>,<op2>

功能:ADD将把两个操作数加起来,把结果放置到目的寄存器中。

Rd=op1+op2操作数1是一个寄存器;操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。例:ADDR0,R1,R2;

R0=R1+R2

ADDR0,R1,#256;

R0=R1+256

ADDR0,R2,R3,LSL#1;

R0=R2+(R3<<1)45451.算术指令-ADCADC带进位加法指令(AdditionwithCarry)ADC{<cond>}{S}<Rd>,<op1>,<op2>功能:将寄存器Rn、操作数op2表示的值以及进位标志位三者相加,然后把结果存入目的寄存器Rd中。它使用一个进位标志位,这样就可以做比32位大的加法。

Rd=op1+op2+carry

进位标志值

46461.算术指令-ADC下列例子将完成两个128位数的相加。128位结果:寄存器0、1、2、和3;第一个128位数:寄存器4、5、6、和7;第二个128位数:寄存器8、9、10、和11。

ADDSR0,R4,R8;

加低端的字

ADCSR1,R5,R9;

加下一个字,带进位

ADCSR2,R6,R10;

加第三个字,带进位

ADCSR3,R7,R11;

加高端的字,带进位47注意:相加时,不要忘记设置S后缀来更改进位标志。1.算术指令-SUB48SUB减法指令(Subtraction)SUB{<cond>}{S}<Rd>,<op1>,<op2>功能:SUB用操作数op1减去操作数op2

,把结果放置到目的寄存器中。

Rd=op1-op2

操作数1是一个寄存器,

操作数2可以是一个寄存器,被移位的寄存器,或一个立即数:

SUBR0,R1,R2; R0=R1-R2

SUBR0,R1,#256; R0=R1-256

SUBR0,R2,R3,LSL#1; R0=R2-(R3左移1位)1.算术指令-SBC49SBC带借位减法指令:(SubtractionwithCarry) SBC{<cond>}{S}<Rd>,<op1>,<op2>功能:用寄存器op1的值减去操作数op2表示的值,再减去进位标志取反的值,然后把结果存入目的寄存器Rd中。它使用进位标志来表示借位,这样就可以做大于32位的减法。

Rd=op1-op2-!carry

SBC生成进位标志时如果需要借位则清除进位标志。所以,指令要对进位标志进行一个非操作,在指令执行期间自动的反转此位。1.算术指令-SBC例如:

第一个64位操作数存放在寄存器R2,R3中;

第二个64位操作数存放在寄存器R4,R5中;

64位结果存放在R0,R1中。

SUBSR0,R2,R4;

低32位相减,S表示结果影响条

件标志位的值

SBCR1,R3,R5;

高32位相减501.算术指令-RSB51RSB反向减法指令(ReverseSubtraction)

RSB{<cond>}{S}<Rd>,<op1>,<op2>功能:SUB用操作数op2减去操作数op1,把结果放置到目的寄存器中。Rd=op2–op1

操作数1是一个寄存器,

操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。RSBR0,R1,R2;

R0=R2-R1

RSBR0,R1,#256;

R0=256-R1

RSBR0,R2,R3,LSL#1;

R0=(R3<<1)-R21.算术指令-RSC52RSC带借位的反向减法指令(ReverseSubtractionwithCarry)RSC{<cond>}{S}<Rd>,<op1>,<op2>功能:同于SBC,但倒换了两个操作数的前后位置。Rd=op2-op1-!carry

例如:第一个64位操作数存放在寄存器R2,R3中;第二个64位操作数存放在寄存器R4,R5中;64位结果存放在R0,R1中。SUBSR0,R2,R4;

低32位相减,S表示结果影响寄存器CPSR的值RSCR1,R5,R3;

高32位相减2.逻辑指令-ANDAND逻辑与指令(logicalAND)

AND{<cond>}{S}<Rd>,<op1>,<op2>功能:AND将在两个操作数上按位进行逻辑与,把结果放置到目的寄存器中:Rd=op1ANDop2。用于清除特定的位;操作数1是一个寄存器操作数2可以是一个寄存器,被移位的寄存器,或一个立即数

例如:ANDR0,R0,#3;

保持R0的位0和1,其余位清0532.逻辑指令-ORRORR逻辑或指令(logicalOR)

ORR{<cond>}{S}<Rd>,<op1>,<op2>功能:OR将在两个操作数上按位进行逻辑或,把结果放置到目的寄存器中,Rd=op1ORop2

;将特定的位置1。操作数1是一个寄存器操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。例如:

ORRR0,R0,#3;

设置R0中位0和1,其余位不变542.逻辑指令-EOREOR逻辑异或指令(logicalExclusiveOR)

EOR{<cond>}{S}<Rd>,<op1>,<op2>功能:EOR将在两个操作数上按位进行逻辑异或,把结果放置到目的寄存器中,Rd=op1EORop2

;将特定的位反转。操作数1是一个寄存器操作数2可以是一个寄存器,被移位的寄存器,或一个立即数例如:EORR0,R0,#3;

反转R0中的位0和1552.逻辑指令-BICBIC位清除指令(BitClear)

BIC{<cond>}{S}<Rd>,<op1>,<op2>;功能:BIC是在一个字中清除位的一种方法,与OR位设置是相反的操作。Rd=op1AND(!op2)

op2是一个32位位掩码(mask)。如果在掩码中设置了某一位,则清除op1中的这一位。未设置的掩码位指示op1中此位保持不变。BICSR0,R2,#0x80000000

;清除R2中的位31,其余的位保持不变,刷新标志位。563.传送指令-MOV57MOV数据传送指令(Move)

MOV{<cond>}{S}<Rd>,<op1>

功能:从另一个寄存器、被移位的寄存器、或一个立即数装载一个值到目的寄存器;

Rd=op1

。指定Rd和op1为同一寄存器,实现NOP指令的效果,或可以实现移位操作。

MOVR0,R0; R0=R0...NOPMOVR0,R0,LSL#3; R0=R0*8如果R15是目的寄存器,将修改程序计数器或标志。用于返回到调用代码,方法是把连接寄存器的内容传送到R15:

MOVPC,R14;

退出到调用者MOVSPC,R14;

退出到调用者并恢复标志位3.传送指令-MVNMVN数据取反传送指令(MoveNegative)

MVN{<cond>}{S}<Rd>,<op1>功能:MVN从另一个寄存器、被移位的寄存器、或一个立即值装载一个被取反的值到目的寄存器;Rd=!op1实际是逻辑非操作:取反的值加1才是它的取负的值.MVNR0,#4; R0=-5

MVNR0,#0;

R0=-1584.乘法指令乘法指令与普通算术指令在对操作数的限制上有所不同:

给出的所有操作数和目的寄存器必须为简单的寄存器。操作数2不能使用立即数或被移位的寄存器。目的寄存器和操作数1必须是不同的寄存器。不能指定R15为目的寄存器。594.乘法指令-MUL(32位)MUL32位乘法指令(Multiplication)

MUL{<cond>}{S}<Rd>,<Rn>,<op2>

功能:MUL提供32位整数乘法。该指令根据S标志,决定操作是否影响CPSR的值。Rn和op2的值为32位的有符号数或无符号数。

Rd=Rn*op2

例如:

MULSR0,R1,R2

;R0=R1×R2,结果影响寄

;存器CPSR的值604.乘法指令-MLA(32位)61MLA32位乘加指令

(MultiplicationwithAccumulate)MLA{<cond>}{S}<Rd>,<Rn>,<op2>,<op3>功能:MLA的行为同于MUL,但它把操作数3的值加到结果上,其中op2,op3必须为寄存器

。Rd=(Rn*op2)+op3,这在求总和时有用Rn、op2和op3的值为32位的有符号数或无符号数。例如:

MLAR0,R1,R2,R3;R0=R1×R2+R31.CMP比较指令(Compare)

CMP{<cond>}<Rn>,<op2>功能:将寄存器Rn的值和操作数op2所表示的值进行比较,根据结果更新CPSR中条件标志位的值。

status=Rn-op2的结果

该指令进行一次减法运算,但不存储结果,只更改条件标志位,后面的指令就可以根据条件标志位来决定是否执行。该指令不需要显式的指定S后缀来更改状态标志。操作数op1为寄存器或立即数。CMPR0,#5;计算R0-5,根据结果设置条件标志位ADDGTR0,R0,#5;如果R0>5,则执行ADDGT指令3.1.3比较指令623.1.3比较指令2.CMN取负比较指令

CMN{<cond>}<Rn>,<op2>CMN指令是比较非指令,也是做一次减法运算,用第1操作数减去第2操作数的负值,结果不保存,只是刷新条件标志位,对条件标志位的影响和比较指令CMP相同。status=Rn–(–op2)的结果例:CMN R1,#0x00 ;比较R1和0xFFFFFFFFADDCSR5,R5,#0x20

;如果C=1,则R5=R5+0x20ADDCCR5,R5,#0x10

;如果C=0,则R5=R5+0x10633.1.3比较指令3.TST位测试指令(Testbits)

TST{<cond>}<Rn>,<op2>功能:将寄存器Rn的值和操作数op2所表示的值按位做逻辑与操作,根据结果更新CPSR中条件标志位的值,但不储存结果。用于检查寄存器Rn是否设置了op2中相应的位。

Status=RnANDop2

64操作数Rn是要测试的数据字而操作数op2是一个位掩码。经过测试后,设置Zero标志。不需要指定S后缀。

TSTR0,#5;

测试R0中第0位和第2位是否为13.1.3比较指令4.TEQ指令 TEQ{<cond>}<Rn>,<op2>TEQ指令是测试指令,用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的异或运算,并根据运算结果更新CPSR中条件标志位的值。该指令通常用于比较操作数1和操作数2是否相等。Status=RnEORop2

例:TEQ R1,#0x10

;将寄存器R1的值与0x10按位异或,并根据结果设置;CPSR的标志位,若Z=1则表示R1的内容是0x10653.1.4分枝指令B和BL分枝和带链接分枝指令,其句法如下:op{cond}label其中:label是程序相对偏移表达式。B指令引起处理器转移到label对应的程序处;BL指令将下一条指令的地址拷贝到R14(即链接寄存器LR)中,并引起处理器转移到label对应的程序处。

663.1.4分枝指令67B分支指令

B{<cond>}<addr>功能:B是最简单的跳转指令。遇到一个B指令,ARM处理器将立即跳转到给定的地址addr,从那里继续执行。

注意:addr的值是相对当前PC(即寄存器R15)的值的一个偏移量;而不是一个绝对地址。它是24位有符号数。实际地址的值由汇编器来计算。addr的值有符号扩展为32位后,左移两位,然后与PC值相加,即得到跳转的目的地址。跳转的范围为-32M~+32M。示例B Label

;程序无条件跳转到标号Label处执行CMP R1,#0

;当CPSR寄存器中的Z条件码置位

;时,程序跳转到标号Label处执行BEQ Label

683.1.4分枝指令2.BL带返回的跳转指令

BL{<cond>}<addr>功能:同B指令,但BL指令执行跳转操作的同时,还将PC(寄存器R15)的值保存到LR寄存器(寄存器R14)中。该指令用于实现子程序调用

。程序的返回可通过把LR寄存器的值复制到PC寄存器中来实现

69例如:BLfunc;

调用子程序func……

func……MOVR15,R14;

子程序返回3.1.5软件中断指令ARM指令集中的软件中断指令是唯一一条不使用寄存器的ARM指令,也是一条可以条件执行的指令。因为ARM指令在用户模式中受到很大的局限,有一些资源不能够访问。所以,在需要访问这些资源时,使用软件控制的唯一方法就是使用软件中断指令SWI。70

指令格式:

语法:

SWI{<cond>} <24位立即数>

软件中断指令SWI产生软件异常中断,用来实现用户模式到特权模式的切换。用于用户模式下对操作系统中特权模式的程序的调用;它将处理器置于管理(svc)模式,中断向量地址为0x08。

说明:主要用于用户程序调用操作系统的API。参数传递通常有两种方法:指令中的24bit立即数指定API号,其它参数通过寄存器传递。忽略指令中的24bit立即数,r0指定API号,其它参数通过其它寄存器传递。condImmed_2402311112728312471

SWI指令举例:

·软中断号在指令中,不传递其它参数

SWI 10 ;中断号为10 SWI 0x123456 ;中断号为0x123456.软中断号在指令中,其它参数在寄存器中传递

MOV R0,#34 ;准备参数

SWI 12 ;调用12号软中断

.不用指令中的立即数,软中断号和其它参数都在寄存器中传递

MOV R0,#12 ;准备中断号

MOV R1,#34 ;准备参数

SWI 0 ;进入软中断723.1.5软件中断指令指令示例:SWI0x02

;实现中断,指明调用2号功能段。思考:它是如何这么作的?它如何传递SWI编号和进入SWI处理程序?73SWI软件中断指令查看内存的开始32字节(位于0-&1C)并反汇编它们(查看实际的ARM指令)将见到如下:

地址内容反汇编

00000000::E5000030:STRR0,[R0,#-48]00000004::E59FF31C:LDRPC,&0000032800000008::E59FF31C:LDRPC,&0000032C0000000C::E59FF31C:LDRPC,&0000033000000010::E59FF31C:LDRPC,&0000033400000014::E59FF31C:LDRPC,&0000033800000018::E59FF31C:LDRPC,&0000033C0000001C::E3A0A632:MOVR10,#&3200000

74SWI软件中断指令一个SWI所做的一切就是把模式改变成管理模式并设置PC来执行在地址&08处的一条指令!转换到管理模式模式,切换掉两个寄存器R13、R14,并用R13_svc和R14_svc替换它们。R14_svc设置为在这个SWI指令之后的地址。这个实际上就象一个连接到地址&08的分支指令(BL&08),但带有用于一些数据(SWI编号)的空间。地址&08包含跳转到另一个地址的一个指令,就是实际的SWI程序的地址!SWI编号呢?实际上处理器忽略这个值本身。SWI处理程序使用传递来的R14_svc的值来获取它。75SWI软件中断指令完成SWI编号的步骤(在存储寄存器r0-r12之后):

它从R14中减去4来获得SWI指令的地址。把这个指令装载到一个寄存器。清除这个指令的高端8位,去掉了OpCode而只剩下的SWI编号。使用这个值来找到要被执行的代码的例程的地址(使用查找表等)。恢复寄存器r0-r12。使处理器离开管理模式。跳转到这个例程的地址。763.1.6汇编器伪指令在ARM汇编语言程序里,有一些特殊指令助记符,这些助记符与指令系统的助记符不同,没有相对应的操作码,通常称这些特殊指令助记符为伪指令,他们所完成的操作称为伪操作。77机器指令、伪指令和宏指令机器指令:能被处理器直接执行,而伪指令和宏指令不能。机器指令包括ARM指令集和Thumb指令集;伪指令:在源程序汇编期间,由汇编编译器处理。其作用是为汇编程序完成准备工作;宏指令:在程序中用于调用宏,宏是一段独立的程序代码;在程序汇编时,对宏调用进行展开,用宏体代替宏指令。78一.ADR语法格式:

ADR{cond}register,exprregister:加载的目标寄存器。expr:地址表达式。当地址值是非字对齐时,取值范围在-255~255字节之间;当地址值是字对齐时,取值范围在-1020~1020字节之间。功能:将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。实现方法:在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现此ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。79例:使用ADR将程序标号Delay所表示的地址存入R1。

……Delay MOVR0,R14 ADRR1,Delay

;把Delay处绝对地址加载给R1

ADRR1,Delay+0x10

;把Delay+0x10处绝对地址加载给R1

……80例:查表

……D_TAB

DCB0xC0,0xF9,0xA4,0xB0,0x99,0x92

ADRR0,D_TAB

;加载转换表地址

LDRBR1,[R0,R2] ;使用R2作为参数,进行查表

……81二.ADRL语法格式:

ADRL{cond}register,exprregister:加载的目标寄存器。expr:地址表达式。当地址是非字对准时,取值范围在-64~64KB之间;当地址是字对准时,取值范围在-256~256KB之间。功能:将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址。实现方法:在汇编编译器编译源程序时,ADRL被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。82

例3: ……Delay MOVR0,R14 …… ADRLR1,Delay+6000

……;将程序标号Delay所表示的地址+6000存入R1。

ADRLR1,0x10

;把距离程序开始处16个地址单元处的绝对地址加载给R1。83三.LDR语法格式:

LDR{cond}register,=exprRegister:加载的目标寄存器。expr:32位常量或地址表达式。功能:用于加载32位立即数或一个地址值到指定的寄存器。实现方法:在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超过MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令;否则汇编器将常量放入文字池(literalpool)/数据缓冲池,并使用一条程序相对偏移的LDR指令从文字池读出常量。84指令示例:LDRR1,=0x20

;加载0x20到R1中;汇编器汇编成;MOVR1,#0x20LDRR1,=0x101

;加载0x101到R1中;汇编器汇编成;LDRR1,[PC,offsect_data1];data1DCD0x101与ARM指令的LDR的区别:伪指令LDR的参数有“=”号。85语法格式:NOPNOP伪指令是空操作指令,在汇编时将被编译成一条无效指令,如MOVR0,R0,占用32位代码空间。NOP伪指令不影响CPSR中的条件标志位。四、NOP86指令示例:ADDRES1LDRR1,=ADDRES2;把ADDRES2地址加载给R1 ADRR2,ADDRES1 ;把ADDRES1地址加载给R2 SUBR3,R1,R2 ;相减

……ADDRES2NOP;空操作87五、数据定义伪指令用于为数据分配存储单元,同时也可完成已分配存储单元的初始化。数据定义有如下几种伪指令:

DCB DCWDCD88五、数据定义伪指令DCB用于分配一块字节单元并用伪指令中指定的表达式进行初始化。格式:标号/变量DCB表达式

DCB可用“=”代替表达式可以为使用双引号的字符串或0-255的数字89指令示例:StringDCB“Thisisatest!”

;分配一片连续的字节存储单元并初始化。DATA2DCB15,25,62,00

;为数字常量15,25,62,00分配内存单元90五、数据定义伪指令DCW/DCWU

格式:标号/变量DCW/DCWU

表达式

DCW分配一段半字存储单元并用表达式值初始化,它定义的存储空间是半字对齐的DCWU功能跟DCW类似,只是分配的字存储单元不严格半字对齐91指令示例:DATA1DCW1,2,3;分配一片连续的半字存储单元并初始化为1,2,3。DATA2DCWU45,0x2a*0x2a

;分配一片非半字对准存储单元并初始化。92五、数据定义伪指令DCD

/DCDU

格式:标号/变量 DCD/DCDU

表达式

DCD用于分配一块字存储单元并用伪指令中指定的表达式初始化,它定义的存储空间是字对齐的。也可用“&”代替DCDU只是分配的存储单元不严格字对齐93指令示例:DATA1DCD 4,5,6 ;分配一片连续的字存储单元并初始化。DATA2DCDLOOP;为LOOP标号的地址值分配一个内存单元。94MAP

格式:MAP表达式[,基址寄存器]MAP定义一个结构化的内存表的首地址,可以用“^”来代替表达式可以为程序中的标号或数学表达式基址寄存器为可选项,当基址寄存器选项不存在时,表达式的值即为内存表的首地址,当该选项存在时,内存表的首地址为表达式的值与基址寄存器的和MAP可以与FIELD伪操作配合使用来定义结构化的内存表。例:

MAP0x130,R2 ;内存表首地址为0x130+R2

95FIELD

格式:标号 FIELD 字节数

FIELD用于定义一个结构化内存表中的数据域,可用“#”来代替FILEDFIELD常与MAP配合使用来定义结构化的内存表:FIELD伪指令定义内存表中的各个数据域,MAP则定义内存表的首地址,并为每个数据域指定一个标号以供其他的指令引用。注意:MAP和FIELD伪指令仅用于定义数据结构,并不分配存储单元。96SPACE

格式:标号 SPACE 表达式

SPACE用于分配一片连续的存储区域并初始化为0,也可用“%”代替表达式为要分配的字节数例:FreespaceSPACE 1000 ;分配1000字节的存储空间97例:MAP0xF10000;定义结构化内存表首地址为;0xF10000countFIELD4;定义count的长度为4字节,;位置为0xF10000x FIELD4;定义x的长度为4字节,位置;为0xF10004y FIELD4;定义y的长度为4字节,位置;为0xF1000898其中:GBLA用于声明一个全局的数字变量,并初始化为0;GBLL伪指令用于声明一个全局的逻辑变量,并初始化为F(假);GBLS伪指令用于声明一个全局的字符串变量,并初始化为空;对于全局变量来说,变量名在源程序中必须是唯一的。

符号定义伪指令用于声明ARM汇编程序中的变量、对变量赋值以及定义寄存器的名称等操作。常见的符号定义伪指令有如下几种:(1)GBLA、GBLL和GBLS六、符号定义伪指令99指令示例:

GBLA DATA1

;声明一个全局数字变量DATA1

GBLL DATA2

;声明一个全局逻辑变量DATA2

GBLS DATA3

;声明一个全局的字符串变量DATA3

DATA3 SETS“Testing”

;将该变量赋值为“Testing”100(2)LCLA、LCLL和LCLS语法格式:

LCLA(LCLL或LCLS) 局部变量名

LCLA、LCLL和LCLS伪指令是声明局部变量伪指令,用于定义一个ARM程序中的局部变量,并将其初始化。其中:LCLA用于声明一个局部的数字变量,并初始化为0;LCLL用于声明一个局部的逻辑变量,并初始化为F(假);LCLS用于声明一个局部的字符串变量,并初始化为空。对于局部变量来说,变量名在使用的范围内必须是唯一的,范围限制在定义这个变量的宏指令程序段内。101指令示例:

LCLA DATA4

;声明一个局部数字变量DATA4

LCLL DATA5

;声明一个局部的逻辑变量DATA5

DATA4 SETA0x10

;为变量DATE4赋值为0x10

LCLS DATA6

;声明一个局部的字符串变量DATA6102(3)SETA、SETL和SETS语法格式: 变量名SETA(SETL或SETS)表达式

SETA、SETL、SETS是变量赋值伪指令,用于给一个已经定义的全局变量或局部变量赋值。其中:SETA用于给一个数学变量赋值;SETL用于给一个逻辑变量赋值;SETS用于给一个字符串变量赋值;103指令示例:

GBLAEXAMP1;先声明一个全局数字变量EXAMP1EXAMP1SETA 0xaa

;将变量EXAMP1赋值为0xaa

LCLLEXAMP2;声明一个局部的逻辑变量EXAMP2

EXAMP2SETL {TRUE};将变量EXAMP1赋值为TRUE

GBLAEXAMP3

;先声明一个全局字符串变量EXAMP3 EXAMP3SETS “string”;将变量EXAMP3赋值为string1043.2Thumb指令集简介为兼容数据总线宽度为16位的应用系统,ARM体系结构除了支持执行效率很高的32位ARM指令集以外,同时支持16位的Thumb指令集。Thumb指令集是ARM指令集的一个子集,允许指令编码为16位的长度。105

Thumb指令长度为16位,这样,与32位的ARM指令集相比,有效地节省了系统的存储空间。Thumb指令集中没有:乘加指令64位乘法指令协处理器指令数据交换指令程序状态寄存器指令指令的第二操作数受到限制,除了跳转指令B有条件执行功能外,其他指令均为无条件执行。1063.2Thumb指令集简介Thumb指令集中的汇编指令助记符与ARM指令集中的汇编指令助记符是相同的,且功能也基本类似。

Thumb指令集与ARM指令集的主要区别体现在以下方面:分支指令方面:Thumb指令集中的条件分支指令与ARM指令集的分支指令相比,在转移范围上有更多的限制,对于子程序的转移只有不带条件的转移指令。107

数据传送指令方面:大多数情况下,Thumb指令集中的数据处理指令对通用寄存器进行操作,操作结果送到其中一个操作数寄存器中,而不是送到第3个寄存器中;另外,除了比较指令(CMP),Thumb指令集中访问R8~R15寄存器的数据处理指令不能更新CPSR寄存器中的标志。108多寄存器加载/存储指令方面:Thumb指令集中采用PUSH指令和POP指令来实现,指令执行以R13作为堆栈指针,实现满递减堆栈;除了加载/存储R0~R7寄存器外,PUSH指令还可存储链接寄存器LR(R14),POP指令可加载程序计数器PC(R15)。Thumb指令集中没有协处理器指令,数据交换指令和访问CPSR/SPSR寄存器的指令。1093.3汇编程序设计在只关心系统所具有功能的设计中,采用高级编程语言编写程序更合适,由于其隐藏了CPU执行指令的许多细节。但是,CPU执行指令的细节差异会反应在系统的非功能特性上,例如系统程序的规模和运行速度。掌握汇编语言程序设计对于嵌入式系统的设计者来说是非常必要的。1103.3.1汇编编程规则ARM汇编程序中每一行的通用格式为:

{标号}{指令|指示符|伪指令}{;注解}除了标号和注释外,指令、伪指令和指示符都必须有前导空格,而不能顶格书写。如果每一行的代码太长,可以使用字符“\”将其分行书写,并允许有空行。指令助记符、指示符和寄存器名既可以用大写字母,也可以用小写字母,但不能混用。注释从“;”开始,到该行结束为止。111一、标号标号代表一个地址,段内标号的地址值在汇编时确定,段外标号的地址值在链接时确定。在此要区别程序相对寻址和寄存器相对寻址。在程序段中,标号代表其所在位置与段首地址的偏移量,根据程序计数器PC和偏移量计算地址称为程序相对寻址。在映像中定义的标号代表标号到映像首地址的偏移量,映像的首地址通常被赋予一个寄存器,根据该寄存器值与偏移量计算地址称为寄存器相对寻址。

112二、预定义变量1 ARM汇编器对ARM的寄存器进行了预定义,所有的寄存器和协处理器名都是大小写敏感的。预定义的寄存器如下:R0~R15和r0~r15;a1~a4(参数、结果或临时寄存器,与r0~r3同义);v1~v8(变量寄存器,与r4~r11同义);sb和SB(静态基址寄存器,与r9同义);sl和SL(堆栈限制寄存器,与r10同义);fp和FP(帧指针,与r11同义);113二、预定义变量2ip和IP(过程调用中间临时寄存器,与r12同义);sp和SP(堆栈指针,与r13同义);lr和LR(链接寄存器,与r14同义);pc和PC(程序计数器,与r15同义);cpsr和CPSR(程序状态寄存器);spsr和SPSR(程序状态寄存器);f0~f7和F0~F7(FPA寄存器);s0~s31和S0~S31(VFP单精度寄存器);d0~d15和D0~D15(VFP双精度寄存器);p0~p15(协处理器0~15);c0~c15(协处理器寄存器0~15)。114三、指示符AREA语法格式:

AREA段名属性1,属性2,……AREA伪指令用于定义一个代码段或数据段。多个属性用逗号分隔,常用的属性如下:CODE属性:用于定义代码段,默认为READONLY。DATA属性:用于定义数据段,默认为READWRITE。READONLY属性:指定本段为只读READWRITE属性:指定本段为可读可写……115一个汇编语言程序至少要包含一个代码段使用示例:AREAInit,CODE,READONLY;该伪指令定义了一个代码段,段名为Init,属性为只读

指令序列 END116ALIGN语法格式:ALIGN{表达式{,偏移量}}ALIGN伪指令可通过添加填充字节的方式,使当前位置满足一定的对齐方式。在默认时,是按字对齐的,表达式的取值范围为0~31,相应的对齐方式为2表达式次方。例如:AREAInit,CODE,READONLY,ALIGN=3;指定后面的指令为8字节对齐指令序列END

117CODE指令语法格式:CODE16或CODE32CODE16和CODE32伪指令是代码长度定义伪指令CODE16伪指令通知编译器,其后的指令序列为16位的Thumb指令。CODE32伪指令通知编译器,其后的指令序列为32位的ARM指令。在使用ARM指令和Thumb指令混合编程的代码里,这两条伪指令后面的代码类型是不同的,但它们并不能对处理器进行状态的切换。118bx的语法格式

BX{<cond>}<Rm><cond>为指令执行的条件码。当<cond>忽略时指令为无条件执行。<Rm>该寄存器中为跳转的目标地址。当<Rm>寄存器的bit[0]为0时,目标地址处的指令为ARM指令;当<Rm>寄存器的bit[0]为1时,目标地址处的指令为Thumb指令。

119指令示例:AREA Example1,CODE,READONLY ENTRY CODE32 ;定义后面的指令为32位的ARM指令START …… LDR R0,=NEXT+1;将跳转地址放入寄存器R0 BX R0 ;程序跳转到新的位置执行,并将处理器切换到Thumb工作状态 …… CODE16 ;定义后面的指令为16位的Thumb指令NEXT LDR R3,=0x3FF ……END ;程序结束120ENTRY语法格式:ENTRY ENTRY伪指令用于指定汇编程序入口点。

在一个完整的汇编程序中至少要有一个ENTRY(也可以有多个,当有多个ENTRY时,程序的真正入口点由链接器指定),但在一个源文件里最多只能有一个ENTRY(可以没有)。使用示例:AREAInitCODE,READONLY ENTRY;指定应用程序的人口点……

121END语法格式:END END伪指令是编译结束伪指令,用于通知编译器已经到了源程序的结尾,每个汇编语言的源程序都必须有一个END伪指令定义源程序结尾。

编译程序检测到这个伪指令后,不再对后面的程序编译。使用示例:AREAInitCODE,READONLY…… END;指定应用程序的结尾122EQU语法格式:名称EQU表达式{,类型} EQU伪指令用于为程序中的标号、数字常量和寄存器的值等定义一个字符名称;

类似于C语言中的#define。

其中EQU可用“*”代替。

可以有以下三种类型:CODE16、CODE32和DATA使用示例:TestEQU50;定义标号Test的值为50Addr

*0x55,CODE32;定义Addr的值为0x55, ;且该处为32位的ARM指令123IMPORT语法格式:IMPORT标号{[WEAK]} IMPORT伪指令用于通知编译器要使用的标号在其他的源文件中定义,但要在当前源文件中引用,而且无论当前源文件是否引用该标号,该标号均会被加入到当前源文件的符号表中。使用示例:AREAInitCODE,READONLYIMPORTMain;通知编译器当前文件要引用标号 ;Main,但Main在其他源文件中定义……END124EXTERN语法格式:EXTERN标号{[WEAK]}EXTERN伪指令用于通知编译器要使用的标号在其他的源文件中定义,但要在当前源文件中引用,如果当前源文件实际并未引用该标号,该标号就不会被加入到当前源文件的符号表中。125EXPORT(或GLOBAL)语法格式:EXPORT标号{[WEAK]

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论