ARM裸机程序开发——ARM寻址方式及指令集

下面总结这几天学习的知识,ARM寻址方式以及指令集

★ARM寻址方式

◇什么是寻址方式

寻址方式是处理器根据指令中给出的地址信息来寻找物理地址的方式,是确定本条指令的数据地址以及下一条要执行的指令地址的方法。ARM寻址方式总有这么几种:立即数寻址、寄存器寻址、寄存器间接寻址、基址变址寻址、多寄存器寻址、相对寻址、堆栈寻址

◇寻址方式的种类

▲立即数寻址(立即寻址)

立即寻址是一种特殊的寻址方式,操作数是在指令中给出,只要取出指令就能得到相应的操作数。这个操作数被称作立即数,对应的寻址方式为立即寻址

例子:ADD R0,R0,#1;这句的意思是将R0+1然后赋值给R0

ADD R0,R0,#0x3f;

其中以#为前缀的数字即为立即数,对于十六进制表示的立即数,还要在#后加上“”0x“或“&”

▲寄存器寻址

寄存器寻址是利用寄存器中的数值作为操作数,这种寻址方式是各类微处理器经常用的一种,也是一种执行效率较高的寻址方式

ADD R1,R2,R0;寄存器R2的值+R0的值赋值给R1

▲寄存器间接寻址

寄存器间接寻址是指以寄存器中的值作为操作数的地址,而操作数本身放在存储器中。例如:

ADD R0,R1,[R2];以寄存器R2的值作为操作数的地址,在存储器中取到一个操作数与R1中的内容相加,结果存入到R0中

LDR R0,[R1];将R1的值为地址的存储器中的数据传送到R0中

▲基址变址寻址

基址变址寻址就是将寄存器(该寄存器一般被称为基址寄存器)的内容与指令中给出的地址偏移量相加,从而得到一个操作数的有效地址。

LDR R0,[R1,#4];R1的内容加上偏移量4得到的内容做为地址,然后取出存储器中这个地址的值加载到R0寄存器中

LDR R0,[R1,#4]!;在上面的指令的基础之上,R1=R1+4

LDR R0,[R1],#4;将存储器中R1寄存器中的内容为地址的内容加载到R0,同时R1=R1+4

LDR R0,,[R1,R2];将存储器中以R1+R2的内容为地址的内容加载到R0中

▲多寄存器寻址

采用多寄存器寻址,一条指令可以完成多个寄存器值得传送。这寻址方式可以用一条指令完成传送最多16个通用寄存器的值

LDMIA  R0,{R1,R2,R3,R4};该指令的后缀IA表示每次执行完加载/存储操作后,R0按字长度增加,因此指令可将连续存储单元的值传送给R1~R4

R1←[R0],R2←[R0+4],R3←[R0+8],R4←[R0+12]

▲相对寻址

相对寻址以程序计数器PC的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。以下程序段完成程序的调用和返回,跳转指令bl采用相对寻址方式

bl NEXT

NEXT:

MOV PC,LR;从子程序返回

▲堆栈寻址

堆栈是一种数据结构,按先进后出的工作方式,使用一个称为堆栈指针的占用寄存器指示当前的操作位置,堆栈指针总是指向栈顶

递增堆栈:向高地址方向增长

递减堆栈:向低地址方向增长

满堆栈:堆栈指针指向最后压入堆栈的有效数据项

空堆栈:堆栈指针指向下一个要放入数据的空位置

★ARM指令集

◇什么是ARM指令集

顾名思义,ARM微处理器指令的集合

◇指令集的分类

▲跳转指令

在ARM中有两种方式可以实现程序的跳转,一种是跳转指令,另一种是直接向PC(R15)寄存器写入目标地址值。

b跳转指令

bl带返回的跳转指令

blx带返回和状态的跳转指令

bx带状态切换的跳转指令

▲数据处理类指令

数据处理类指令可分为数据传送指令、算数逻辑运算指令、比较指令。数据传送指令用于在寄存器和存储器之间进行数据的双向传输。算数逻辑运算指令完成常用的算数与逻辑的运算,该类指令不但将运算结果保存在目的寄存器中,同时更新CPSP中的相应条件标志位

△数据传递

◆MOV指令

MOV指令格式

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

MOV指令完成从一个寄存器、被移位的寄存器或将一个立即数加载到目的寄存器。其中S选项决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。

MOV  R1,R0;将寄存器R0的值传递给R1

MOV  PC,LR;将链接寄存器中的值传递给PC,常用于子程序的返回

MOV  R1,R0,LSL #3;将寄存器R0的值左移3位后传送到R1

◆MVN指令

MVN {条件} {S} 目的寄存器 源寄存器

MVN指令可完成从一个寄存器、被移位寄存器,或者将一个立即数加载到目的寄存器。与MOV指令不同之处是在传送之前按位被取反了,即把一个取反的值传递给目的寄存器。其中S决定指令的操作是否影响CPSP中条件标志位的值

MVN R0 ,#0xff;R0←0xffffff00(先将源操作数按位取反)

◆CMP指令

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

CMP指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行比较,同时更新CPSP中条件标志位的值。该指令进行一次减法运算,但不存储结果,值更改条件标志位。标志位表示的是操作数1与操作数2的关系(大、小、相等),例如当操作数1大于操作数2的时候,则此后的有GT后缀的指令将可以执行

CMP R1,R0;将寄存器R0的值与R1的值相减,并根据结果设置CPSR的标志位

CMP R1,#100;将寄存器R1的值与立即数相减,并根据结果设置CPSR的标志位

◆TST指令

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

TST指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的与运算,并根据运算结果更新CPSR中条件位的值。操作数1是要测试的数据,而操作数2是一个位掩码,根据测试结果设置相应标志位。当位与结果为0时,EQ位被设置

TST R1,#%1;用于测试在寄存器R1中是否设置了最低位(%表示二进制数)

◆ADD指令

ADD {条件} {S} 目的寄存器,操作数1,操作数2

ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器或者一个立即数

ADD R0,R1,R2;R0=R1+R2

ADD R0,R1,#256;R0=R1+256

ADD R0,R2,R3,LSL#1;R0=R2+(R3<<1)

◆AND指令

AND {条件} {S} 目的寄存器,操作数1,操作数2

AND指令用于在两个数上进行逻辑与运算,并把结果放置在目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。该指令常用于屏蔽操作数1的某些位。

AND R0,R0,#3;该指令保持R0的0,1位,其余位清零

◆ORR指令

ORR {条件} {S} 目的寄存器,操作数1,操作数2

ORR指令用于在两个操作数上进行逻辑或运算,并把结果放置在目的寄存器中。操作数1应是一个寄存器,操作数2也是一个寄存器或是被移位的寄存器或是一个立即数。该指令常用于设置操作数1的某些位

ORR R0 ,R0 ,#3;该指令设置R0的0,1位,其余位保持不变。因为执行的是逻辑或操作,操作R0的0,1位被置1

◆BIC指令

BIC {cond} {S} Rd,Rn,operand2

BIC(位清除)指令对Rn中的值与operand2值得反码按位进行逻辑与运算

BIC R0,R0,#0xF0000000;对R0中的高四位清零

BIC R0,R0,#0x0F;对R0的低四位清零

◆MUL指令

MUL {条件} {S} 目的寄存器,操作数1,操作数2

MUL指令完成将操作数1余操作数2的乘法运算,并把结果放置在目的寄存器,同时可以根据运算结果设置CPSR中相应的条件表示位。其中,操作数1和操作数2均为32位的有符号或者无符号数

MUL R0,R1,R2;R0=R1*R2

MULS R0,R1,R2;R0=R1*R2,同时设置CPSR中的相关条件标志位

▲程序状态寄存器访问指令

ARM微处理器支持程序状态寄存器访问指令,用于在程序状态寄存器和通用寄存器之间传递数据

△MRS指令

MRS {条件} 通用寄存器 程序状态寄存器(CPSR或SPSR)

MRS指令用于将程序状态寄存器的内容传送到通用寄存器

该指令使用的情况:

当需要改变程序状态寄存器的内容时,可用MRS将程序状态寄存器的内容读入通用寄存器,修改后再写回程序状态寄存器

当在异常处理或进程切换时,需要保存程序状态寄存器中的值,可先用该指令读出程序状态寄存器的值,然后保存

MRS R0,CPSR;传送CPSR的内容到R0

MRS R0,SPSR;传送SPSR的内容到R0

△MSR指令

MSR {条件} 程序状态寄存器(CPSR或SPSR)_<域>,操作数

MSR指令用于将操作数的内容传送到程序状态寄存器的特定域中。其中,操作数可以为通用寄存器或立即数。<域>用于设置程序状态寄存器中需要操作的位,32位的程序可分为4个域:

位[31:24]为条件标志位域,用f表示;

位[23:16]为状态位域,用s表示;

位[15:8]为扩展位域,用x表示;

位[7:0]为控制位域,用c表示;

该指令通常用于恢复或改变程序状态寄存器的内容,在使用时,一般要在MSR指令中指明将要操作的域

MSR CPSR ,R0;传送R0的内容到CPSR

MSR SPSR ,R0;传送R0的值到SPSR

MSR CPSR_c,R0;传送R0的值到SPSR,但仅仅修改COSR中的控制位域

▲加载/存储指令

ARM微处理器支持加载/存储指令用于在寄存器与寄存器之间传送数据,加载指令用于将存储器中的数据传送到寄存器,存储指令则完成相反的操作

△LDR 指令的格式为:

LDR {条件} 目的寄存器,<存储器地址>

LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中,该指令通常用于从存储器中读取32位字数据到通用寄存器,然后对数据进行处理。

△STR指令的格式为:

STR {条件} 源寄存器,<存储器地址>

STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。

STR R0,[R1],#8;将R0中的字数据写入以R1为地址的存储器中,并且R1 = R1+8

STR R0,[R1,#8];将R0中的字数据写入以R1+8位地址的存储器中

▲数据交换指令

△SWP指令格式

SWP {条件} 目的寄存器,源寄存器1,[源寄存器2]

SWP指令用于将源寄存器2所指向的存储器中的字数据传送的目的寄存器中,同时将源寄存器1中的字数据传递给源寄存器2所指向的存储器中。显然当源寄存器1和目的寄存器为同一寄存器时,指令交换该寄存器和存储器的内容

SWP R0,R1,[R2];将R2所指向的存储器中的字数据传递给R0,同时将R1中的字数据传递给R2所指向的存储单元

SWP R0,R0,[R1];该指令完成将R所指向的存储器中的字数据与R0中的字数据交换

▲位移指令

ARM微处理器支持数据的移位操作,移位操作在ARM指令中不作为单独的指令使用,它只能作为指令格式中的一个字段,在汇编语言中表示位指令中的选项。移位操作包括以下6中类型,ASL和LSL是等价的,可以自由互换:

△LSL逻辑左移

LSL操作格式:通用寄存器,LSL操作数

LSL可完成对通用寄存器中的内容进行逻辑左移操作,按操作数所指定的数量向左移动,低位用零来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)

操作示例:MOV R0,R1,LSL#2

将R1中的内容左移两位后传送到R0中

△ASL算数右移

△LSR逻辑右移

△ASR算数右移

△ROR循环右移

ROR操作格式为:通用寄存器,ROR操作数

ROR可完成对通用寄存器中的内容进行循环右移的操作,按操作数所指定的数量向右循环右移,左端用右端移出的位来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。显然,当进行32位的循环右移操作时,通用寄存器中的值不改变。

操作示例:MOV R0,R1,ROR#2

将R1中的内容循环右移两位后到R0中

▲异常产生指令

△SWI软件中断指令

△BKPT端点中断指令

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值