C语言实现无条件状态切换,ARM Cortex M3指令集

一、跳转指令

跳转指令用于实现程序流程的跳转,在ARM 程序中有两种方法可以实现程序流程的跳转:

Ⅰ.使用专门的跳转指令。

Ⅱ.直接向程序计数器PC 写入跳转地址值。

通过向程序计数器PC 写入跳转地址值,可以实现在4GB 的地址空间中的任意跳转,在跳转之前结合使用 MOV LR,PC 等类似指令,可以保存将来的返回地址值,从而实现在4GB 连续的线性地址空间的子程序调用。

ARM指令集中的跳转指令可以完成从当前指令向前或向后的32MB的地址空间的跳转,包括以下4 条指令:

1、 B 指令

B 指令的格式为:

B{条件} 目标地址

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

B Label ;程序无条件跳转到标号Label 处执行

CMP R1,#0 ;当CPSR 寄存器中的Z 条件码置位时,程序跳转到标号Label 处执行

BEQ Label

2、 BL 指令

BL 指令的格式为:

BL{条件} 目标地址

BL 是另一个跳转指令,但跳转之前,会在寄存器R14 中保存PC 的当前内容,因此,可以通过将R14 的内容重新加载到PC 中,来返回到跳转指令之后的那个指令处执行。该指令是实现子程序调用的一个基本但常用的手段。以下指令:

BL Label ;当程序无条件跳转到标号Label 处执行时,同时将当前的PC 值保存到R14 中

3、 BLX 指令

BLX 指令的格式为:

BLX 目标地址

BLX 指令从ARM 指令集跳转到指令中所指定的目标地址,并将处理器的工作状态有ARM 状态切换到Thumb 状态,该指令同时将PC 的当前内容保存到寄存器R14 中。因此,当子程序使用Thumb 指令集,而调用者使用ARM 指令集时,可以通过BLX 指令实现子程序的调用和处理器工作状态的切换。同时,子程序的返回可以通过将寄存器R14 值复制到PC 中来完成。

4、 BX 指令

BX 指令的格式为:

BX{条件} 目标地址

BX 指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM 指令,也可以是Thumb 指令。

ARM7TDMI(-S)具有32位ARM指令集和16位Thumb指令集。

ARM指令集效率高,但是代码密度高

Thumb指令集具有较高的代码密度,却仍然保持着ARM的大多数性能上的优势,它是ARM的子集。

所有的ARM置零都是可以条件执行的,而Thumb置零仅有一条指令具备条件执行的功能。

ARM和Thumb程序可以相互调用,相互之间状态切换开销几乎为零。

首先我们来看一下分类:

一、数据处理指令操作数寻址方式

1、立即数寻址方式

2、寄存器寻址方式

3、寄存器移位寻址方式

二、存储器访问指令操作数寻址方式

1、寄存器间接寻址

2、基址变址寻址

3、相对寻址

4、多寄存器寻址(块拷贝寻址)

5、堆栈寻址

下面来一一介绍:

ARM有9种寻址方式

寻址方式:

1、立即寻址:

立即寻址指令中的操作码字段后面的部分就是操作数本省,也就是说,数据就包含再指令,取指令也就取出了可以立即使用的操作数。举例:

SUBS   R0,R0,#1              ;R0减1,结果放入R0中,并且影响标志位

MOV    R0,#0xFF000          ;将立即数0xFF000装入R0寄存器

ARM规定:这个立即数必须符合8位图格式,负责必须使用“文字池”方式,通过存储器访问指令加载,所谓的8位图格式就是指,这个数据能通过一个8bit的数循环右移偶数位得到。

2、寄存器寻址:

操作数的值在寄存器中,指令中的地址字段指出的是寄存器的编号,指令执行的时候直出寄存器值来操作。举例:

MOV   R1,R2                ;将R2的值存入R1

MOV   R0,R1,R2              ;将R1的值减去R2的值,结构存到R0

3、寄存器移位寻址

寄存器移位寻址是ARM处理器特有的寻址方式。当第二个操作数是寄存器移位方式时,第二个操作数在与第一个操作数结合之前,选择进行移位操作。举例:

MOV    R0,R2,LSL #3      ;R2的值左移3位,结果放入R0,即R0=R2*8

ANDS  R1,R1,R2,LSL R3    ;R2的值左移R3位,然后和R1相"与"操作,结构放入R1

可采用移位操作的指令如下:

LSL左移、LSR右移、ASR算术右移、ROR循环右移、RRX带扩展的循环右移

4、寄存器间接寻址:

寄存器间接寻址指令中的地址码给出的是一个通用寄存器的编号,所需的操作数保存再寄存器指定地址的存储单元中,即寄存器为操作数的地址指针,举例:

LDR   R1,[R2]          ;将R2指向的单元中的数据保存再R1中

SWP   R1,R1,[R2]       ;将寄存器R1的值和R2指向的单元中进行内容交换

5、基址变址寻址:

基址寻址就是将基址寄存器的内容与指令中给出的偏移量进行相加,形成操作数的有效地址。

基址寻址用于访问基址附近的存储单元,常用于查表、数组操作以及功能不见寄存器访问等

举例:

LDR   R2,[R3,#0x0c]     ; 读取R3 0x0c地址指向的存储单元的内容,放入R2

STR   R1,[R0,#-4]!       ;先R0=R0-4,然后把R1的值寄存到R0所指向的单元中

LDR   R1,[R0,R3,LSL #1]  ;将R0 R3*2地址上的单元的内容读出,并存入R1中

6、相对寻址:

相对寻址是基址寻址的一种变通。由程序计数器PC提供基址地址,指令中的地址码字段为偏移量。两者相加后得到的地址即为操作数的有效地址。

7、多寄存器寻址:

多寄存器寻址即一次可传送几个寄存器的值,允许一条指令传送16个寄存器的任何子集或

所有的存储器,举例:

LDMIA   R1!,{R2-R7,R12};将R1指向的单元中的数据读出到R2---R7、R12中(R1自自动 )

STMIA   R0!,{R2-R7,R12};将R2---R7、R12中的数据一次读入到R0指向的单元中(R0自动 )

8、堆栈寻址(块拷贝寻址):

堆栈是一种按特定顺序进行存取的存储区,操作顺序分为“先进后出”和“后进先出”,堆栈寻址是隐含的,它使用一个专门的寄存器(堆栈指针)指向的存储区域(堆栈),指针所指向的存储单元即是堆栈的栈顶。

存储器堆栈可以分为两种:

向上生长:递增堆栈

向下生长:递减堆栈

还有从当前堆栈指针指向的内容是否有效可以分为:满递增、空递增、满递减、空递减

举例:

STMFD    SP!,{R1-R7,LR}    ;将R1---R7、LR入栈。满递减堆栈

LDMFD    SP!,{R1-R7,LR}    ;数据出栈,放入R1---R7、LR寄存器,满递减堆栈

ARM指令的基本格式

ARM指令的基本格式为:

{}  {S}  ,  { , }

其中,内的项是必需的,{  }内的项是可选的。

(1)Opcode项

Opcode是指令助记符,即操作码,说明指令需要执行的操作,在指令中是必需的。

(2)Cond项(command)

Cond项表明了指令的执行的条件,每一条ARM指令都可以在规定的条件下执行,每条ARM指令包含4位的条件码,位于指令的最高4位[31:28]。条件码共有16种,每种条件码用2个字符表示,这两个字符可以添加至指令助记符的后面,与指令同时使用。当指令的执行条件满足时,指令才被执行,否则指令被忽略。如果在指令后不写条件码,则使用默认条件AL(无条件执行)。

指令的条件码条 件 码助记符后缀标    志含    义

0000EQZ置位相等equal

0001NEZ清零不相等not equal

0010CSC置位无符号数大于或等于Carry Set

0011CCC清零无符号数小于

0100MIN置位负数minus

0101PLN清零正数或零plus

0110VSV置位溢出

0111VCV清零没有溢出

1000HIC置位Z清零无符号数大于high

1001LSZ置位C清零无符号数小于或等于less

1010GEN等于V带符号数大于或等于

1011LTN不等于V带符号数小于least

1100GTZ清零且(N等于V)带符号数大于great

1101LEZ清零或(N不等于V)带符号数小于或等于

1110AL忽略无条件执行all

1111

条件码应用举例:

例:比较两个值大小,并进行相应加1处理,C语言代码为:

if  ( a > b )  a++;

else  b++;

对应的ARM指令如下(其中R0中保存a 的值,R1中保存b的值):

CMP  R0, R1  ; R0与R1比较,做R0-R1的操作

ADDHI  R0, R0, #1  ;若R0 > R1, 则R0 = R0 + 1

ADDLS  R1, R1, #1  ; 若R0 <= R1, 则R1 = R1 + 1

CMP比较指令,用于把一个寄存器的内容和另一个寄存器的内容或一个立即数进行比较,同时更新CPSR中条件标志位的值。指令将第一操作数减去第二操作数,但不存储结果,只更改条件标志位。

CMP  R1, R0  ;做R1-R0的操作。

CMP  R1,#10  ;做R1-10的操作。

(3) S项(sign)

S项是条件码设置项,它决定本次指令执行的结果是否影响至CPSR寄存器的相应状态位的值。该项是可选的,使用时影响CPSR,否则不影响CPSR。

(4)Rd项(destination)

Rd是指令中的目标寄存器,它是必需的。根据指令的不同,有些指令中要求Rd必须有R0~R7之间,有些要求Rd必须在R0~R14之间,有些则没有特殊要求。

(5)Rn项

Rn是第一个操作数的寄存器,和Rd一样,不同的指令对其的使用有不同的要求。

(6)Opcode2项

Opcode2项是第二个操作数,在ARM指令中,该操作数有三种形式:立即数形式、寄存器Rm形式和寄存器加移位形式(Rm, shift)。

例如:

SUB  R3,  R1,  #10

SUB  R3,  R1,  R2

SUB  R3,  R1,  R2,  LSL  #2

SUB  R3,  R1,  R2,  LSL  R0

ARM指令详解

ARM指令集可分为以下6类:

l  跳转指令

l  数据处理指令

l  程序状态寄存器(PSR)处理指令

l  加载/存储指令

l  协处理器指令

l  异常产生指令

ARM指令及功能描述助 记 符指令功能描述

ADC带进位加法指令

ADD加法指令

AND逻辑与指令

B跳转指令

BIC位清零指令

BKPT软件断点

BL带返回的跳转指令

BLX带返回和状态切换的跳转指令

BX带状态切换的跳转指令

CDP协处理器数据操作指令

CMN取反比较指令

CMP比较指令

EOR逻辑异或指令

LDC存储器到协处理器的数据传输指令

LDM加载多个寄存器的指令

LDR存储器到寄存器的数据传输指令

MCR从ARM寄存器到协处理器寄存器的数据传输指令

MLA乘加运算指令

MOV数据传输指令

MRC从协处理器寄存器到ARM寄存器的数据传输指令

MRS传送CPSR或SPSR的值到通用寄存器的指令

MSR传送通用寄存器的值到CPSR或SPSR的指令

MUL32位乘法指令

MVN数据取反传送指令

ORR逻辑或指令

RSB反向减法指令

RSC带借位的反向减法指令

SBC带借位的减法指令

STC协处理器寄存器写入存储器指令

STM存储多个寄存器的值到存储器指令

STR存储寄存器的值到存储器的指令

SUB减法指令

SWI软件中断指令

SWP寄存器与存储器 或 寄存器与寄存器之间的数据交换指令

TEQ相等测试指令

TST位测试指令

1. 跳转指令

用于实现程序流程的跳转,在ARM程序中有两种方法可以实现程序流程的跳转:一是使用专门的跳转指令,二是直接向程序计数器PC写入跳转地址值。第二种方法可以实现在4GB的地址空间中的任意跳转,在跳转之前结合使用“MOV LR , PC”等类似指令,可以保存将来的返回地址值,从而实现在4GB连续的线性地址空间的子程序调用。

1)ARM指令集中的跳转指令可以实现从当前指令向前或向后的32MB的地址空间的跳转。

l  B指令

格式:

B{条件}  目标地址

注意,存储在跳转指令中的实际值是相对当前PC值的一个偏移量,而不是一个绝对地址,它的值由汇编器来计算(相对寻址)。这个偏移量是一个24位的有符号数,左移两位后表示的有效偏移为26位(前后32MB的地址空间)。{}表示可以省略。

如:B Label     程序无条件跳转到标号Label处执行。

CMP R1,#0

BEQ Label

当CPSR寄存器中的Z条件码置位时,程序跳转到Label处执行。

当前PC:是指跳转指令本身的起始地址。

l  BL指令

格式:

BL{条件}  目标地址

这条指令在跳转之前,会在寄存器R14中保存当前的下一条指令的地址,因此,可以通过将R14重新加载到PC中,来返回到跳转指令之后的那条指令处执行。该指令是实现子程序调用的一种常用手段。

l  BX 指令

格式:

BX {条件}  目标地址

BX指令中所指定的目标地址,只能使用寄存器的寻址方式,即跳转的目标地址应先保存在一个寄存器中。指令在实现跳转的同时,完成处理器的工作状态的切换(ARM状态与Thumb状态间的切换)。

BX指令中,用寄存器的最低位来指示切换到哪一个工作状态。如寄存器最低位为1,则把目标地址处的代码解释为Thumb代码,进入Thumb工作状态,并自动将CPSR中的控制位T置1。若寄存器最低位为0,则把目标地址处的代码解释为ARM代码,进入ARM工作状态,并自动将CPSR中的控制位T置0。

ADRL  R0,  ThumbFun + 1     ;生成分支地址并置最低位为 1

BX  R0    ;跳转到R0所指定的地址,并切换处理器到Thumb工作状态

ThumbFun

…         ;Thumb汇编指令

| BLX指令

以上两条指令的综合。

2. 数据处理指令

数据处理指令可分数据传送指令、算术逻辑运算指令和比较指令等。数据传送指令用于在寄存器和存储器之间进行数据的双向的传输。所有ARM数据处理指令均可选择使用S后缀,以影响状态标志CPSR。比较指令(CMP、CMN、TST、TEQ)不保存运算结果,这些指令也不使用S后缀,但会直接影响CPSR中的相应的状态标志位。

(1)数据传送指令MOV 和MVN

格式:

MOV {条件} {S} 目的寄存器, 源操作数

MOV指令可以完成从另一个寄存器、被移位的寄存器、或将一个立即数加载到目的寄存器。与MVN指令不同的是在传送之前,将被传送的对象先按位取反,再传送到目的寄存器。

例:MVN  R1 ,  #0XFF    ;R1 ← 0X FFFF FF00

MVN  R1 ,  R2

MOV PC,R14;将寄存器R14的值传送给PC,用于子程序返回。

(2) 数据比较指令CMP , CMN , TST , TEQ

例:

CMP  R1,  R2  ; 做R1 – R2 的操作,结果不保存,但影响标志位。

CMP R1 , #10  ;做R1 - 10的操作,结果不保存,但影响标志位。

CMN 指令用于把一个寄存器的内容和另一个寄存器的内容或立即数取反后进行比较操作,根据运算结果影响CPSR中的标志位。该指令实际完成操作数1和操作数2相加,并根据结果更改条件标志位。

TST位测试指令,用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的与运算,并根据运算结果更新CPSR中条件标志位的值。操作数1是要测试的数,而操作数2 是一个位掩码,该指令一般用来检测是否设置了特定的位。

TST {条件} 操作数1, 操作数2

c2c9ed493cd281aa86d8a6f5178c4c01.gif [1] [2] [3] 610626052e95c7fbe3d254abc769d9ad.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值