05-ARM体系结构与常用汇编指令

一、ARM体系结构

 ARM(Advanced RISC Machines) ,既可以认为是一个公司的名字,也可以认为是对一类微处理器的通称,还可以认为是一种技术的名字。ARM 处理器是一种低功耗高性能的 32 位RISC 处理器,基于 ARM 的处理器以其高速度、低功耗等诸多优异的性能而得到非常广泛的应用。  ARM公司在经典处理器ARM11以后的产品改用Cortex命名,并分成A、R和M三类,其分别应用于不同的领域。Cortex系列属于ARMv7架构,其中“A”系列面向尖端的基于虚拟内存的操作系统和用户应用;“R”系列针对实时系统;“M”系列对微控制器。在ARM11推出前,其处理器比较:

| | ARM7 | ARM9 |ARM10|ARM11| | -------- | -------- | -------- ||| | 流水线 | 3级 |5级| 6级| 8级| |典型频率MHz| 80| 150| 260 |335| |功耗mW/MHz| 0.06| 0.19(+cache) |0.5 (+cache)|0.4 (+cache) | |性能MIPS/MHz| 0.97| 1.1| 1.3| 1.2| |架构| 冯*诺伊曼| 哈佛| 哈佛| 哈佛|  冯诺伊曼结构与哈佛结构的区别:

 在TQ2440开发板上使用的是S3C2440芯片。这是一款基于ARM920T核心的微处理器芯片,采用哈佛结构使用5级指令流水线包括:取指、译码、执行、存储及写入。各步骤作用分别为: (1)取指令(fetch):从存储器中取出指令,并将其放入指令流水线。 (2)译码(decode):指令被译码,从寄存器堆中读取寄存器操作数。在寄存器堆中有3个操作数读端口,因此,大多数ARM指令能在1个周期内读取其操作数。 (3)执行(execute):将其中1个操作数移位,并在ALU中产生结果。如果指令是Load或Store指令,则在ALU中计算存储器的地址。 (4)缓冲/数据(buffer/data):如果需要则访问数据存储器,否则ALU只是简单地缓冲1个时钟周期。 (5)回写(write-back):将指令的结果回写到寄存器堆,包括任何从寄存器读出的数据。 1.1ARM基本数据类型  ARM采用的是32位架构,基本数据类型有3种:Byte(字节), 8bit;Halfword(半字),16bit(半字必须2字节边界对齐);Word(字), 32bit(字必须于4字节边界对齐)。  长度为1个字的数据项占用一组4字节的位置,该位置开始于4的倍数的地址(地址最末两位为00)半字占有两个字节的位置,该位置开始于偶数字节地址(地址最末一位为0)。 1.2存储器大/小端  大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。例如变量word a=0xf6734bcd,使用大/小端存储格式完全不一样。    1.3ARM编程模型  要想了解ARM920T为内核芯片的主要可以从几个方面入手:工作模式、ARM异常种类、寄存器组织、运行状态。  ARM920T是基于ARM V4T 架构,共有7种工作模式:

处理器 描述
用户模式(usr) ARM 处理器正常的程序执行状态。
快速中断模式(fiq) 用于高速数据传输或通道处理。
外部中断模式(irq) 用于通常的中断处理。
管理模式(svc) 操作系统使用的保护模式。
数据访问终止模式(abt) 当数据或指令预取终止时进入该模式,可用于虚拟存储及存储保护。
系统模式(sys) 运行具有特权的操作系统任务。
未定义指令中止模式(und) 当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真。

 七种工作模式又可以从两个方面划分:特权模式与非特权模式;异常模式与非异常模式。

划分方式 说明
特权模式与非特权模式 用户模式外的其他6种处理器模式称为特权模式(Privileged Modes)。在特权模式下,程序可以访问所有的系统资源,也可以任意地进行处理器模式切换,而用户模式不能直接切换到别的模式。
异常模式与非异常模式 除去用户模式和系统模式以外的 5 种又称为异常模式(ExceptionModes),常用于处理中断或异常,以及需要访问受保护的系统资源等情况。

 在异常模式下,有着不同的异常,其对应关系为:

异常 向量表 模式
复位(Reset) 0x00 管理模式
未定义指令(Undefined Instruction) 0x04 未定义指令中止模式
软中断(Software Interrupt) 0x08 管理模式
指令预取异常(Prefetch Abrot) 0x0C 数据访问终止模式
数据异常(Data Abort) 0x10 数据访问终止模式
保留(Reserved) 0x14 /
中断(IRQ) 0x18 数据访问终止模式
快速中断(FIQ) 0x1C 快速中断模式

 ARM 处理器共有 37 个寄存器,被分为若干个组(BANK)。31 个通用寄存器,包括程序计数器(PC 指针),均为 32 位的寄存器;6 个状态寄存器,1个CPSR(Current Program Status Register,当前程序状态寄存器),5个SPSR(Saved Program Status Register,备份程序状态寄存器),用以标识 CPU 的工作状态及程序的运行状态,均为 32 位。ARM有7种不同的处理器模式,在每一种处理器模式中有一组相应的寄存器组。   在汇编语言中寄存器R0~R13为保存数据或地址值的通用寄存器。它们是完全通用的寄存器,不会被体系结构作为特殊用途,并且可用于任何使用通用寄存器的指令。这些通用寄存器根据其分组与否可分为以下2类。未分组寄存器(the Unbanked Register),包括R0~R7;分组寄存器(the Banked Register),包括R8~R14。   未分组寄存器没有被系统用于特殊的用途,任何可采用通用寄存器的应用场合都可以使用未分组寄存器。但由于其通用性,在异常中断所引起的处理器模式切换时,其使用的是相同的物理寄存器,所以也就很容易使寄存器中的数据被破坏。   分组寄存器根据处理器模式使用方法有所不同:

分组寄存器 说明
R8~R12 每个寄存器对应两个不同的物理寄存器。一组用于除FIQ模式外的所有处理器模式,而另一组则专门用于FIQ模式。
R13和R14 每个寄存器对应6个不同的物理寄存器。其中的一个是用户模式和系统模式公用的,而另外5个分别用于5种异常模式。访问时需要指定它们的模式。名字形式:R13_<mode>、R14_<mode>。<mode>可以是以下几种模式之一:usr、svc、abt、und、irp及fiq。R13寄存器在ARM处理器中常用作堆栈指针,称为SP ;寄存器R14又被称为连接寄存器(Link Register,LR)。

  程序计数器R15( PC),它指向正在取指的地址,在异常模式中,另外一个寄存器“ 程序状态备份寄存器( SPSR) ” 可以被访问。每种异常都有自己的SPSR,在进入异常时它保存CPSR的当前值,异常退出时可通过它恢复CPSR。该寄存器的位分配图为:

寄存器位 作用
N位 符号位。如果结果为负数,则N = 1;如果结果为正数或0,则 N = 0
Z位 如果指令的结果为0,则置1(通常用来表示比较的结果为“相等”);否则置0
C位 表示运算的进位、借位等
V位 益出标志位
Q标志位 在带DSP指令扩展的ARM v5及更高版本中,bit[27]被指定用于指示增强的DAP指令是否发生了溢出,因此也就被称为Q标志位。同样,在SPSR中bit[27]也被称为Q标志位,用于在异常中断发生时保存和恢复CPSR中的Q标志位。在ARM v5以前的版本及ARM v5的非E系列处理器中,Q标志位没有被定义,属于待扩展的位。
I = 1 IRQ被禁止
F = 1 FIQ被禁止
T位 处理器的状态控制位。T = 0,处理器处于ARM状态(即正在执行32位的ARM指令)。T = 1,处理器处于Thumb状态(即正在执行16位的Thumb指令)。T位只有在T系列的ARM处理器上才有效,在非T系列的ARM版本中,T位将始终为0。
M[4∶0] 作为位模式控制位,其具体控制模式可见下表。

  ARM处理器的运行状态可以分为ARM与Thumb两种状态。其中ARM状态下PC值为字对齐(4字节),Thumb状态下PC值为半字对齐(2字节)。

二、ARM的指令系统

  在嵌入式开发中,汇编程序常常用于非常关键的地方,比如系统启动时的初始化,进出中断时的环境保存、恢复,对性能要求非常苛刻的函数等。ARM 微处理器的指令集主要有 6 大类:跳转指令、数据处理指令、程序状态寄存器(PSR)处理指令、加载/存储指令、协处理器指令、异常产生指令。 2.1跳转指令  跳转(B)和跳转连接(BL)指令是改变指令执行顺序的标准方式。ARM一般按照字地址顺序执行指令,需要时使用条件执行跳过某段指令。只要程序必须偏离顺序执行,就要使用控制流指令来修改程序计数器。主要有三条指令:

指令 语法格式 跳转范围
跳转指令B及带连接的跳转指令BL B{L}{<cond>} <target_address> PC+-32MB
BX带状态切换的跳转指令BX BX{<cond>} <Rm> 绝对地址4G
BXL带状态切换的连接跳转指令BLX BLX <target_add> 绝对地址4G

2.2数据处理指令  在了解ARM的数据处理指令之前要知道ARM的寻址方式,数据处理指令寻址方式可以分为3种:立即数寻址方式;寄存器寻址方式;寄存器移位寻址方式。其语法格式为: <opcode> {<cond>} {S} <Rd>,<Rn>,<shifter_operand>,其中,<shifter_operand>有11种形式 。

数据指令寻址方式 指令
立即数寻址 指令中的立即数是由一个8bit常数移动4bit偶数位得到的。
ADD R3,R3,#1 ;R3的值加1
CMP R7,#1000 ;R7的值和1000比较
BIC R9,R8,#0xFF00 ;将R8中8~15位清零,结果保存在R9中
寄存器寻址方式 寄存器的值可以被直接用于数据操作指令,这种寻址方式是各类处理器经常采用的一种方式,也是一种执行效率较高的寻址方式。
ADD R4,R3,R2 ;R2加R3,结果送R4
CMP R7,R8 ;比较R7和R8的值
寄存器移位寻址方式 寄存器的值在被送到ALU之前,可以事先经过桶形移位寄存器的处理。预处理和移位发生在同一周期内,所以有效地使用移位寄存器,可以增加代码的执行效率。
MOV R1,R0,LSL #2
RSB R9,R5,R5,LSL #1

内存访问指令寻址方式主要有以下几种。

寄存器指令寻址方式 含义
寄存器间接寻址 指令中的地址码给出的是一个通用寄存器编号,所需要的操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针,操作数存放在存储器中。
LDR R0,[R1] ; R0←[R1](将R1中的数值作为地址,取出此地址中的数据保存在R0中)
STR R0,[R1] ; [R1] ←R0
寄存器指令寻址方式 含义
变址寻址 将基址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址,变址寻址用于访问基址附近的存储单元,常用于查表,数组操作,功能部件寄存器访问等。
LDR R2,[R3,#4] ; R2←[R3 + 4](将R3中的数值加4作为地址,取出此地址的数值保存在R2 中)
STR R1,[R0,#-2] ; [R0-2] ← R1
多寄存器寻址 含义
变址寻址 采用多寄存器寻址方式,一条指令可以完成多个寄存器值的传送,这种寻址方式用一条指令最多可以完成16个寄存器值的传送。
LDMIA R0,{R1,R2,R3,R5} ; R1←[R0]
(IA表示是后递增方式); R2←[R0 + 4]
(IB表示是先递增方式) ; R3←[R0 + 8]
(DA和DB表示后递减和先递减) ; R5←[R0 + 12]
多寄存器寻址 含义
堆栈寻址 堆栈操作顺序分为“后进先出”和“先进后出”,堆栈寻址时隐含的,它使用一个专门的寄存器(堆栈指针)指向一块存储区域(堆栈),指针所指向的存储单元就是堆栈的栈顶。

向上生长:向高地址方向生长,称为递增堆栈;向下生长:向低地址方向生长,称为递减堆栈。 堆栈指针指向最后压入的堆栈的有效数据项, 称为满堆栈(Full Stack);堆栈指针指向下一个要放入的空位置,称为空堆栈( Empty Stack)。

堆栈工作方式 说明
满递增堆栈 堆栈指针指向最后压入的数据,且由低地址向高地址生成。如指令LDMFA, STMFA 等。
满递减堆栈 堆栈指针指向最后压入的数据,且由高地址向低地址生成。如指令LDMFD, STMFD 等。
空递增堆栈 堆栈指针指向下一个将要放入数据的空位置,且由低地址向高地址生成。如指令LDMEA, STMEA 等。
空递减堆栈 堆栈指针指向下一个将要放入数据的空位置,且由高地址向低地址生成。如指令LDMED, STMED 等。

  数据操作指令是指对存放在寄存器中的数据进行操作的指令。包括:数据传送指令、 算术指令、 逻辑指令、 比较与测试指令及乘法指令。 如果在数据处理指令后使用S前缀,指令的执行结果将会影响CPSR中的标志位。   ARM乘法指令完成两个数据的乘法。两个32位二进制数相乘的结果是64位的积。

乘法指令 说明
MUL指令 MUL(Multiply)32位乘法指令将Rm和Rs中的值相乘,结果的最低32位保存到Rd中
MLA乘—累加指令 MLA(Multiply Accumulate)32位乘—累加指令将Rm和Rs中的值相乘,再将乘积加上第3个操作数,结果的最低32位保存到Rd中。
UMULL指令 UMULL(Unsigned Multiply Long)为64位无符号乘法指令。它将Rm和Rs中的值做无符号数相乘,结果的低32位保存到RsLo中,高32位保存到RdHi中。
UMLAL指令 UMLAL(Unsigned Multiply Accumulate Long)为64位无符号长乘—累加指令。指令将Rm和Rs中的值做无符号数相乘,64位乘积与RdHi、RdLo相加,结果的低32位保存到RsLo中,高32位保存到RdHi中。
SMULL指令 SMULL(Signed Multiply Long)为64位有符号长乘法指令。指令将Rm和Rs中的值做有符号数相乘,结果的低32位保存到RsLo中,高32位保存到RdHi中。
SMLAL指令 SMLAL(Signed Multiply Accumulate Long)为64位有符号长乘—累加指令。指令将Rm和Rs中的值做有符号数相乘,64位乘积与RdHi、RdLo相加,结果的低32位保存到RsLo中,高32位保存到RdHi中。

2.3加载/存储指令   Load/Store内存访问指令在ARM寄存器和存储器之间传送数据。 ARM指令中有3种基本的数据传送指令。单寄存器Load/Store指令( Single Register);’多寄存器Load/Store内存访问指令;单寄存器交换指令( Single Register Swap)。

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

示例代码:
LDR R2,[R5] ;将R5指向地址的字数据存入R2
STR R1,[R0,#0x04] ;将R1的数据存储到R0+0x04地址
LDRB R3,[R2],#-1 ;将R2指向地址的字节数据存入R3, R2=R2-1
指令 说明
多寄存器的Load/Store内存访问指令 多寄存器的Load/Store内存访问指令也叫批量加载/存储指令,它可以实现在一组寄存器和一块连续的内存单元之间传送数据。 LDM用于加载多个寄存器, STM用于存储多个寄存器。

示例代码:
	LDR R0,=SrcData ;设置源数据地址
	LDR R1,=DstData ;设置目标地址
	LDMIA R0,{R2~R9} ;加载8字数据到寄存器R2~R9
	STMIA R1,{R2~R9} ;存储寄存器R2~R9到目标地址
指令 说明
单数据交换指令 交换指令是Load/Store指令的一种特例,它把一个寄存器单元的内容与寄存器内容交换。

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

( 1)MRS指令的语法格式: 
		MRS{cond} Rd, PSR;Rd为目标寄存器, Rd不允许为程序计数器( PC)。 PSR为CPSR或SPSR。
指令举例:
		MRS R1,CPSR ;将CPSR状态寄存器读取,保存到R1中
		MRS R2,SPSR ;将SPSR状态寄存器读取,保存到R1中
(2)MSR指令的语法格式
	MSR{cond} PSR_field,#immed_8r 或MSR{cond} PSR_field,Rm
		&lt;fields&gt;设置状态寄存器中需要操作的位。状态寄存器的32位可以分为4个8位的域( field)。 
					bits[31: 24]为条件标志位域,用f表示; 
					bits[23:16]为状态位域,用s表示; 
					bits[15: 8]为扩展位域,用x表示; 
					bits[7: 0]为控制位域,用c表示; 
					immed_8r为要传送到状态寄存器指定域的立即数, 8位; 
					Rm为要传送到状态寄存器指定域的数据源寄存器。
指令举例:
		MSR CPSR_c,#0xD3 ;CPSR[7:0]=0xD3,切换到管理模式
		MSR CPSR_cxsf,R3 ;CPSR=R3

2.5协处理器指令  ARM协处理器指令可分为3类:协处理器数据操作, CDP;协处理器数据传送指令,包括LDC和STC;协处理器寄存器传送指令,包括MCR和MRC。

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

三、ARM-THUMB 子程序调用规则 ATPCS

 为了使 C 语言程序和汇编程序之间能够互相调用,必须为子程序间的调用制定规则,在ARM 处理器中,这个规则被称为 ATPCS: ARM 程序和 Thumb 程序中子程序调用的规则。 基本的ATPCS 规则包括寄存器使用规则、数据栈使用规则、参数传递规则。 3.1、寄存器使用规则 ARM 处理器中有 r0~r15 共 16 个寄存器, 它们的用途有一些约定的习惯,并依具这些用途定义了别名,如下表所示:

寄存器 别名 使用规则
Text Text Text
r15 pc 程序计数器
r14 lr 连接寄存器
r13 sp 数据栈指针
r12 ip 子程序内部调用的 scratch 寄存器
r11 v8 ARM 状态局部变量寄存器 8
r10 v7、 s1 ARM 状态局部变量寄存器 7、在支持数据栈检查的 ATPCS 中为数据栈限制指针
r9 v6、 sb ARM 状态局部变量寄存器 6、在支持 RWPI 的 ATPCS 中为静态基址寄存器
r8 v5 ARM 状态局部变量寄存器 5
r7 v4、 wr ARM 状态局部变量寄存器 4、 Thumb 状态工作寄存器
r6 v3 ARM 状态局部变量寄存器 3
r5 v2 ARM 状态局部变量寄存器 2
r4 v1 ARM 状态局部变量寄存器 1
r3 a4 参数/结果/scratch 寄存器 4
r2 a3 参数/结果/scratch 寄存器 3
r1 a2 参数/结果/scratch 寄存器 2
r0 a1 参数/结果/scratch 寄存器 1

3.2、 数据栈使用规则  数据栈有两个增长方向:向内存地址减小的方向增长时,称为 DESCENDING 栈;向内地址增加的方向增长时,称为 ASCENDING 栈。  所谓数据栈的增长就是移动栈指针。当栈指针指向栈顶元素(最后一个入栈的数据)时,称为 FULL 栈;当栈指针指向栈顶元素(最后一个入栈的数据)相邻的一个空的数据单元时,称为 EMPTY 栈。  综合这两个特点, 数据栈可以分为以下 4 种:① FD Full Descending,满递减;② ED Empty Descending,空递减;③ FA Full Ascending,满递增;④ EA Empty Ascending,空递增。  ATPCS 规定数据栈为 FD 类型,并且对数据栈的操作是 8 字节对齐的。 使用 stmdb/ldmia批量内存访问指令来操作 FD 数据栈。 3.3、 参数传递规则  一般来说,当参数个数不超过 4 个时,使用 r0~r3 这 4 个寄存器来传递参数;如果参数个数超过 4 个,剩余的参数通过数据栈来传递。对于一般的返回结果, 通常使用 a0~a3 来传递。

本站公众号
   欢迎关注本站公众号,获取更多程序园信息
开发小院