ARM指令集

1 篇文章 0 订阅
1 篇文章 0 订阅

数据处理指令

数据操作指令是指将存放在寄存器中的数据进行操作的指令。主要包括数据传送指令、算数指令、逻辑指令、比较与测试指令及乘法指令。如果在数据处理指令后使用“S”后缀,指令的执行结果将会影响CPSR中的标志位。数据处理指令的基本语法格式如下:

<opcode> { <cond> } { S } < Rd >, < Rn >, < shifter_oprand >

 

数据处理指令列表

助记符

操作

行为

MOV

数据传送

 

MVN

数据取反传送

 

ADD

Rd: =Rn + shifter_operand

ADC

带进位的加

Rd: =Rn + shifter_operand + C

SUB

Rd: =Rn - shifter_operand

SBC

带借位的减

Rd: =Rn - shifter_operand - !C

RSB

逆向减

Rd: =shifter_operand - Rn

RSC

带借位逆向减

Rd: =shifter_operand - Rn - !C

AND

逻辑与

Rd: =Rn AND shifter_operand

ORR

逻辑或

Rd: =Rn OR shifter_operand

EOR

逻辑异或

Rd: =Rn EOR shifter_operand

BIC

位清0

Rd: =Rn AND NOT shifter_operand

CMP

比较

Rn - shifter_operand 并更新标志位

CMN

相反数比较

Rn + shifter_operand 并更新标志位

TST

位测试

Rn AND shifter_operand 并更新标志位

TEQ

测试相等

Rn EOR shifter_operand 并更新标志位

 

 

乘法指令

ARM有两类乘法指令:一类是32位的乘法指令,即乘法操作后的结果是32位;另一类为64位乘法指令,即乘法操作后的结果是64位。

 

各种形式乘法指令

操作码[23:21]

助记符

意义

操作

000

MUL

乘(保留32位结果)

Rd = ( Rm × Rs ) [ 31:0 ]

001

MLA

乘(保留32位结果)

Rd = ( Rm × Rs + Rn ) [ 31:0 ]

100

UMULL

无符号数长乘

RdHi: RdLo = Rm × Rs

101

UMLAL

无符号数长乘——累加

RdHi: RdLo += Rm × Rs

110

SMULL

有符号数长乘

RdHi: RdLo = Rm × Rs

111

SMLAL

有符号数长乘——累加

RdHi: RdLo += Rm × Rs

 

各个乘法指令中的的位S(参考下文具体的语法格式)控制条件码设置会产生以下结果。

(1)对于产生32位结果指令形式,标志位N的置为寄存器Rd的第31位的值一致;对于产生64位结果的指令形式,标志位N的置为寄存器RdHi的第31位的值一致。

(2)对于产生32位结果的指令形式,如果寄存器Rd等于零,则标志位Z置位;对于产生长乘结果的指令形式,RdHi和RdLo同时为零时,标志位Z置位。

(3)乘法指令对C位不产生影响。

(4)乘法指令对V位不产生影响。

 

跳转指令

跳转指令B和BL均可以跳转到目标地址处执行。ARM在一般情况下按照顺序逐条执行存储在内存当中的指令,但有些情况下需要跳转到另一段区域去执行,比如子程序调用时。这时,就要使用跳转指令来改变程序的顺序执行。实现程序的跳转一般有两种方式,一是使用跳转指令,另一种方式是直接向PC寄存器中写入目标地址的值。

 

ARMv5架构跳转指令

助记符

操作

说明

B

跳转指令

pc <—— label

BL

带返回的跳转指令

pc <—— label(同时将BL下一条指令地址给LR)

BX

跳转并切换状态

pc <—— Rm&0xfffffffe, T <—— Rm[ 0 ]

 

BLX

 

带返回的跳转并切换状态

pc <—— label, T <—— 1

pc <—— Rm&0xfffffffe, T <—— Rm[ 0 ]

rl <—— BLX后面的第一条指令的地址

 

 

Load/Store指令

Load/Store内存访问指令是一类可以在ARM寄存器和存储器之间进行数据传递的指令。ARM指令中有3种基本的数据传送指令。

(1)单寄存器Load/Store指令(Single Register):这些指令可以在ARM寄存器和存储器之间灵活地进行单数据项数据交换。数据项可以是字节、16位半字和32位字。

(2)多寄存器Load/Store内存访问指令:这些指令的灵活性比单寄存器传送指令差,但可以进行批量的数据交换。它们用于进程的进入和退出、保存和恢复工作寄存器以及复制存储器中的一块数据。

(3)单寄存器交换指令(Single Register Swap):这个指令允许寄存器和存储器中的数值进行交换,在一条指令中有效地完成内存与寄存器之间的数据交换。它们在用户级编程中很少用到。它的主要用途是在处理器系统中实现信号量(Semaphorea)的操作,以保证不会同时访问公用的数据结构。

1. 单寄存器Load/Store指令

这种指令用于把单一的数据传入或者传出一个寄存器。支持的数据类型有字节(8位)、半字(16位)和字(32位)。

 

单寄存器的Load/Store指令

指令

作用

操作

LDR

把存储器中的一个字装入一个寄存器

Rd 《—— mem32 [ address ]

STR

把寄存器中的字保存到存储器

Rd ——》mem32 [ address ]

LDRB

把一个字节装入一个寄存器

Rd 《—— mem8 [ address ]

STRB

将寄存器中的低8位字节保存到存储器

Rd ——》mem8 [ address ]

LDRH

把一个半字装入一个寄存器

Rd 《—— mem16 [ address ]

STRH

将寄存器中的低16半字保存到存储器

Rd ——》mem16 [ address ]

LDRBT

用户模式下将一个字节装入寄存器

Rd 《—— mem32 [ address ]

STRBT

用户模式下将寄存器中的低8位字节保存到存储器

Rd ——》mem8 [ address ] under user mode

LDRT

用户模式下把一个字装入一个寄存器

Rd《—— mem32[ address ] under user mode

STRT

用户模式下将存储器中的字保存到寄存器

Rd ——》mem32[ address ] under user mode

LDRSB

把一个有符号字节装入一个寄存器

Rd《—— {mem8[ address ]}

STRSB

把一个有符号半字装入一个寄存器

Rd《—— {mem16[ address ]}

 

 

2. 多寄存器Load/Store内存访问指令

多寄存器的Load/Store内存访问指令也叫批量加载/存储指令,它可以实现在一组寄存器和一块连续的内存单元之间传送数据。LDM用于加载多个内存寄存器,STM用于存储多个寄存器。多寄存器的Load/Store内存访问指令允许一条指令传送16个寄存器的任何子集或所有寄存器。

多寄存器的Load/Store内存访问指令主要用于现场保护、数据恢复和参数传递等。

 

多寄存器的Load/Store内存访问指令

指令

作用

操作

LDM

装载多个寄存器

{Rd} *N 《—— mem32 [ start address + 4*N ]

STM

保存多个寄存器

{Rd} *N ——》mem32 [ start address + 4*N ]

 

 

3.单数据交换指令

单数据交换指令是Load/Store指令的一种特例,它把一个寄存器单元的内容与寄存器内容交换。交换指令是一个原子操作(Atomic OPeration),也就是说,在连续的总线操作中读/写一个存储单元,在操作期间阻止其他任何指令对该存储单元的读/写。

 

交换指令

指令

作用

操作

SWP

字交换

tmp = mem32[Rn] ; mem32[Rn] = tmp ; Rd = tmp

SWPB

字节交换

tmp = mem8[Rn] ; mem8[Rn] = tmp ; Rd = tmp

状态寄存器传输指令

ARM指令集提供了两条指令,用于读写程序状态寄存器(Program State Register, PSR)。MRS指令用于把CPSR或SPSR的值传送到一个寄存器;MSR与之相反,把一个寄存器的内容传送到CPSR或SPSR。这两条指令相结合,可用于对CPSR和SPSR进行读/写操作。

 

程序状态寄存器指令

指令

作用

操作

MRS

把程序状态寄存器的值送到一个通用寄存器

Rd=PSR

MSR

把通用寄存器的值送到程序状态寄存器或把一个立即数送到程序状态寄存器

PSR [ field ] = Rm 或 PSR [ field ] = immediate

 

在指令语法中可以看到一个称为filed的项,它可以是控制(C)、扩展(X)、状态(S)及标志(F)的组合。

其中PSR是指CPSR或SPSR。field设置状态寄存器中需要操作的位。状态寄存器的32位可以分为4个8位的域(field)。

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

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

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

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

只有在特权模式下才能修改状态寄存器!!

程序中不能通过MSR指令直接修改CPSR中的T位控制位来实现ARM状态/Thumb状态的切换。必须使用BX指令来完成(因为BX指令属转移指令,它会打断流水线状态,实现处理器状态的切换)。MSR与MSR配合使用,实现CPSR或SPSR寄存器的“读——修改——写”操作,可用来进行处理器模式切换及允许/禁止IRQ/FIQ中断等设置。

 

协处理器指令

ARM体系结构允许通过增加协处理器来扩展指令集。最常用的协处理器是用于控制片上功能的系统协处理器。例如,控制Cache和存储管理单元的CP15协处理器。此外,还有用于浮点运算的浮点ARM协处理器,各生产商还可以根据需要开发自己的专用协处理器。ARM协处理器具有自己专用的寄存器组,它们的状态由控制ARM状态的指令的镜像指令来控制。

程序的控制流指令由ARM处理器来处理,所有协处理器指令只能同数据处理和数据传送有关。按照RISC的Loader/Store体系原则,数据的处理和传送指令是被清楚分开的,因此它们有不同的指令格式。

ARM处理器支持16个协处理器,在程序执行过程中,每个协处理器忽略ARM和其他协处理器指令。当一个协处理器硬件不能执行属于它的协处理器指令时,将产生一个未定义指令异常中断,在该异常中断处理过程中,可以通过软件仿真该硬件操作。比如如果一个系统中不包含向量浮点运算器,则可以选择浮点运算软件包来支持向量浮点运算。

ARM协处理器可以部分地执行一条指令,然后产生中断,如除法运算除数为0和溢出,这样可以更好地处理运行时产生run-time-generated的异常。但是,指令的部分执行是由协处理器完成的,此过程对ARM来说是透明的。当ARM处理器重新获得执行时,它将从产生异常的指令处开始执行。

对某一个协处理器来说,并不一定用到协处理器指令中的所有的域。具体协处理器如何定义和操作完全由协处理器的制造商自己决定,因此,ARM协处理器指令中的协处理器寄存器的标识符及操作助记符也有各种不同的实现定义。程序员可以通过宏来定义这些指令的语法格式。

ARM协处理器指令可分为以下3类:

(1)协处理器数据操作。协处理器数据操作完全是协处理器内部操作,它完成协处理器寄存器的状态改变。如浮点加运算,在浮点协处理器中将两个寄存器相加,结果放在第3个寄存器中。这类指令包括CDP。

(2)协处理器数据传送指令。这类指令可以实现从寄存器读取数据装入协处理器寄存器,或可将协处理器的数据装入存储器。因为协处理器可以支持自己的数据类型,所以每个寄存器传送的字数与协处理器有关。ARM处理器产生存储器地址,但传送的字节由协处理器控制。这类指令包括LDC指令和STC指令。

(3)协处理器寄存器传送指令。在某些情况下,需要ARM处理器和协处理器之间传递数据。如一个浮点运算协处理器,FIX指令从协处理器寄存器取得浮点数据,将它转换为整数,并将整数传送到ARM寄存器中。经常需要用浮点比较产生的结果来影响控制流,因此,比较结果必须传送到ARM的CPSR中。这类协处理器寄存器传送指令包括MCR和MRC。

 

所有协处理器处理指令

助记符

操作

CDP

协处理器数据操作

LDC

装载协处理器寄存器

MCR

从ARM寄存器传数据到协处理寄存器

MRC

从协处理寄存器传输局到ARM寄存器

STC

存储协处理器寄存器

 

 

异常产生指令

ARM指令集中提供了两条产生异常的指令,通过这两条指令可以用软件的方法产生异常。

 

ARM异常产生指令

助记符

含义

操作

SWI

软中断指令

产生软中断,处理器进入管理模式

BKPT

断点中断指令

处理器产生软件中断

 

1.中断指令

软件中断指令(Software Interrupt, SWI)用于产生软中断,实现从用户模式变换到管理模式,CPSR保存到管理模式的SPSR中,程序跳转到异常向量表对应的位置去执行。在其他模式下也可以使用SWI指令,处理器同样切换到管理模式。

在SWI指令中包括了一个24位的立即数,该立即数指示了用户请求的特定的SWI功能。因此当SWI指令触发一次异常处理程序时,异常程序首先要从SWI指令中提取出来中断号,及SWI指令中的立即数的值,从而得到用户请求的特定的SWI功能。一般情况下SWI异常中断的处理分为两级,第一级的SWI处理函数用于从SWI指令中读取24位的中断号,第一级通常由汇编语言来完成。第二级SWI异常处理程序通常实现各个SWI的具体功能,第二级处理可以是汇编程序也可以是C程序。在第一级SWI异常处理程序中通过LR寄存器中的值可以得到SWI指令在内存中的地址,并通过内存读取指令可以将该地址中指令的机器码读取出来并从机器码中提取24位的中断号。

2.断点中断指令

断点中断指令(Breakpoint, BKPT)产生一个预取异常(Prefetch Abort),它常被用来设置软件断点,在调试程序时十分有用。当系统存在调试硬件时,该指令被忽略。

指令格式如下:

BKPT <immediate>

要正确使用BKPT指令,必须和具体的调试系统相结合。一般来说,BKPT有两种使用方法。

(1)如果当前使用的系统调试硬件没有屏蔽BKPT指令,那么在此系统中预取指令异常和软件调试命令同时使用一个中断向量。这样当异常发生时,就要依靠系统自身来判断是真正的预取异常还是软件调试命令。根据系统的不同,判断的方法也有所不同。

(2)如果当前的系统调试硬件屏蔽了BKPT指令,那么系统会跳过BKPT指令顺序执行该指令下面的程序代码。

 

                                                                                                                                              ——《ARM嵌入式体系结构与接口技术》

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值