目录
考点1 嵌入式处理器的结构类型
考点2 嵌入式处理器简介
考点3 ARM处理器概述
考点4 处理器和处理器核
考点5 ARM 处理器的分类
考点6 经典 ARM 处理器
考点7 ARM Cortex 嵌入式处理器
考点8 ARM Cortex实时嵌入式处理器
考点9 ARM Cortex 应用处理器
考点10 ARM 处理器的工作状态及工作模式
考点11 ARM 处理器的寄存器组织
考点12 ARM处理器的异常
考点13 ARN的存储器格式要求及数据类型
考点14 ARM 处理器中的 MMU 和 MPU
考点15 ARM 指令分类及指令格式
考点16 ARM 指令的寻址方式
考点17 ARM 指令集
考点18 Thumb 指令集
考点19 ARM 处理器支持的伪指令
考点20 ARM 汇编器所支持的伪指令
考点21 ARM汇编语言的语句格式
考点22 汇编语言的程序设计举例
考点23 嵌入式C语言与汇编语言混合程序设计
23考纲
考点1 嵌入式处理器的结构类型
(1)CISC处理器与 RISC 处理器
①指令集的概念
指令集(Instruction Set)也称为指令系统,内容包括基本数据类型、寄存器、寻址模式、指令、中断、异常处理以及外部 I0 等,它是设计处理器的主要依据,常常被称为指令集体系结构或IS架构(Instruction SetArchitecture, ISA).
②CISC 处理器的特点
指令集中指令数目很多且结构比较复杂,它包含许多很少使用的专用指令,不同指令的长度并不相等,执行时间也长短不一。CISC处理器结构复杂,功耗较大。
③RISC 处理器的特点
指令数目较少,指令字长统一,格式规整,寻址模式较为单纯,指令操作简单,执行时间短,大多能在1个周期内完成。所有需要处理的操作数都必须经过加载和存储指令从存储器取出后预先存放在寄存器。
④RISC 与 CISC 的关系
RISC与CISC并不是对立的,它们在竞争的过程中相互借鉴,取长补短。
(2)冯·诺依曼存储结构与哈佛存储结构
①冯·诺依曼存储结构与哈佛存储结构的区别
不同之处是:CPU连接程序存储器与数据存储器的方式不同。
②)冯·诺依曼结构的特点
CPU(运算器与控制器)与存储器的连接只有一套总线,也就是一套数据线、控制线和地址线连接了 CPU 与存储器,存储器中可以存放数据,也可以存放程序。冯氏结构中数据和程序代码共享同一地址空间,程序代码可作为数据来处理,反之亦然,因而具有较好的灵活性。
③哈佛结构的特点
a.使用两个独立的存储器分别存储指令和数据,不允许指令和数据并存;
b.使用独立的两条总线,分别作为CPU与每个存储器之间的专用通信路径,而这两条总线之间毫无关联哈佛结构的处理器其程序和数据分开组织与存储,执行时可以同时进行指令和数据的存取,因而具有较高的执行效率。许多数字信号处理器和微控制器都使用哈佛结构,它们的程序代码和数据量较小,分别存放在 Flash 和SRAM 存储器中。
考点2 嵌入式处理器简介
内核系列 | 推出公司 | 内核结构 | 简单描述 |
51 | Intel | CISC哈佛结构 | 8位字长,最早被称为单片机。其价格低,应用资料全,开发工具便宜,开发周期短,开发成本低,被广泛应用。 |
AVR | Atmel | RISC哈佛结构 | 8位、16位和32位三类字长的微控制器内核,主要特点是高性能、高速度、低功耗。 |
PIC | Microchip | RISC哈佛结构 | 8位、16位和32位三类不同字长的RISC微控制器内核。主要针对工业控制应用领域,应用最广的是电机控制、汽车电子等抗干扰要求比较高的场合。PIC的主要优势是针对性强,特别是抗干扰能力强 |
MSP430 | TI | RISC冯·诺依曼结构 | 16位字长的微控制器内核,既集成了数字电路,也集成了模拟电路。广泛应用于手持设备嵌入式应用系统中,突出特点就是以超低功耗著称全球。 |
MIPS | MIPS | RISC哈佛结构 | 高性能、高档次32位(MIPS32)和64位(MIPS64)处理器内核,主要特点是适应于高速、大数据吞吐量应用场合。 |
PowerPC | Apple, IBM,Motorola | RISC哈佛结构 | PowerPC是含有32位子集的64位高性能处理器内核。具有优异的性能、较低的能耗以及较低的散热量。 |
MC68K | Motorola,Freescale | RISC哈佛结构 | 32位字长的处理器内核,具有超标量的超级指令流水线,性能优势明显,主要应用在高端嵌入式应用领域 |
ColdFire | Freescale | RISC哈佛结构 | 32位的高性能微控制器内核。其性能优越,集成度高,可应用于工业控制领域、消费电子领域、医疗电子领域、测试与测量领域等 |
ARM | ARM | RISC多数为哈佛结构 | 除64位的Cortex-A50外,均为32位结构的嵌入式处理器内核。是全球应用最广、知名度最高、使用厂家最多的嵌人式处理器内核 |
考点3 ARM处理器概述
(1)ARM 处理器的主要特点
①单周期操作
ARM 指令系统中的指令只需要执行简单而基本的操作,其执行过程在一个机器周期内完成。
②只使用加载/存储(Load/Store)指令访问内存
只采用加载和存储两种指令对存储器进行读和写的操作,所有需要运算部件进行处理的操作数都必须经过加载指令和存储指令,从存储器取出后预先存放到寄存器内,以加快指令的执行速度。
③指令长度固定
指令格式固定为 32位长(在16位代码的 Thumb 工作状态除外),使指令译码结构简单,效率提高。
④三地址指令格式
采用三地址指令格式(Thumb指令为二地址)、较多寄存器和对称的指令格式便于编译器生成优化的代码。
⑤指令流水线技术
ARM 采用多级流水线技术(3级~13级),以提高指令执行的效率。
⑥)低功耗设计
ARM 处理器架构简单,有利于高效并且极其简单地实现,门电路数目大大减少。此外,它还采取硬件性能监视、动态时钟控制、动态电压调节、省电模式等多种节能措施,主流 ARM 为 32位处理器。主要特点有耗电省、功能强、成本低、32位和16位指令集并存。
(2)ARM处理器指令集的比较
除Cortex-M之外,其他ARM 处理器都有 ARM指令集和 Thumb/Thumb-2两套指令集,这两套指令集都是逐步扩展的,高版本处理器与低版本处理器保持向下基本兼容(注:v8架构的处理器还有64位的A64指令集)。
①ARM 指令集
ARM 指令集全部是 32 位的指令,其基本指令主要用于进行8位、16位和 32 位整数的运算,通过扩展的协处理器(最多16个),可以扩充浮点运算指令、数字信号处理(DSP)指令、单指令多数据(SIMD)指令等。
②)Thumb 指令集
Thumb 全部是 16 位字长的指令,可以看作是 ARM 指令的压缩形式。它是为减少代码量而设计的,因为较短的指令整体上可以有更高的代码密度。Thumb 指令集并不完备,它只支持通用功能,必要时仍需要使用 ARM指令。
③Thumb-2 指令集
Thumb-2指令集既有 16 位指令又有 32位指令,是一个混合的指令集。它是 16位 Thumb 指令集的超集,功能强大、完备,效率高。由于 Thumb-2 同时支持 16位和 32 位指令,因而无须像 Thumb 指令那样麻烦地在 Thumb状态和 ARM 状态之间来回切换处理器的工作状态。
考点4 处理器和处理器核
(1)处理器核
“处理器核”特指实现某种版本 ARM 指令集架构、具有取指令和执行指令功能的组件。
(2)处理器
以处理器核为中心,再把存储管理部件 MM、中断控制器、浮点运算器、总线接口等组件进行集成就构成“ARM 处理器”。
ARM 处理器中一定包含有一个或几个处理器核,而单纯的处理器核也可以作为处理器使用。
考点5 ARM 处理器的分类
ARM 处理器分为五类:
经典 ARM处理器、ARM Cortex嵌入式处理器、ARM Cortex 实时嵌入式处理器ARM Cortex应用处理器以及ARM专家处理器
ARM Cortex 处理器包括:
(1)Cortex-A(A=Application)系列是面向高端应用的处理器,它的工作频率高、性能好、功耗合理。A5~A15为32位,而 A53-A57为64位版本。
(2)Cortex-R(R=RealTime)系列是面向实时控制应用的处理器,响应速度快、性能合理、功耗低。
(3)Cortex-M(M=Microcontroller)系列是面向微控制器的处理器,性价比极高、成本很低、功耗极小。
考点6 经典 ARM 处理器
经典 ARM 处理器目前主要有ARM7、ARM9和ARM11三个系列,包含多种不同的处理器,它们大多是按照ARM4T、ARMV5TE或ARMv6架构设计的。
(1)ARM7 系列
ARM7系列的 ARM7TDMI(ARM7TDMS-S)是市场上销量最高的32位处理器内核,它采用ARMv4T架构,支持 ARMThumb指令集,使用冯氏存储结构,由3级指令流水线实现
(2)ARM9系列
ARM920T 处理器使用的核是ARM9TDMI,它基于ARMv4T架构设计,支持ARM/Thumb 指令集,具有快速乘法器;采用程序与数据分离的哈佛存储结构,指令Cache和数据 Cache各 16KB,还可通过总线外接 Cache和 SRAM 存储器;支持协处理器:含有内嵌的在线仿真模块ICE、支持片上调试:采用5级流水线以提高处理器性能,每一条指令的执行分为5个步骤:①取指令,②指令译码,③执行指令运算,④Cache/存储器访问,⑤结果写回寄存器。
考点7 ARM Cortex 嵌入式处理器
(1)Cortex-M的介绍
Cortex-M 系列目前包括 Cortex-M0/M0+/M1/M3/M4共5款处理器。它们保持向上兼容,具有高能效、易使用的特点,能以低成本提供丰富的功能,适用于对成本和功耗敏感的微控制器(MCU)和终端应用。Cortex-M 处理器都是 32位的 RISC 处理器,采用流水线技术,它只支持 Thumb-2指令集的子集。
(2)Cortex-M0(CM0)
①Cortex-M0(CM0)的特点
ARM Cortex-M0 处理器是现有的体积最小、能耗最低的 ARM 处理器。CM0的处理器核基于ARMV6M架构(是ARM7M架构的子集),它仅有56条Thumb-2指令,用户很容易掌握,开发比较简单。它采用冯氏存储结构、3级流水线技术,可配置硬件乘法器,确定的指令执行时间和中断计时使得很容易计算出事件响应时间。
②Cortex-M0(CM0)的结构CM0处理器的结构如图 2-6所示。其中,WIC(Wake-up Interrupt Controller)为唤醒中断控制器,NVIC(Nestedvector Intermupt Controller)为嵌套向量中断控制器。32位的 AMBA-3AHB-Lite 系统总线提供了与外部组件和存诸器的简单接口。
(3)Cortex-M3(CM3)
CM3处理器系列的低功耗、低成本和易于使用的优点相结合。它采用的处理器核是基于 ARMV7-M 架构,使用哈佛存储结构和3级流水线实现,支持 Thumb-2指令集的子集,有硬件除法指令。
①总线矩阵和嵌套向量中断控制器
与处理器核集成在一起的是总线矩阵和嵌套向量中断控制器(NVC),前者提供了3条AHB-Lite 总线,分别用于连接指令存储器、数据存储器和作为系统总线。嵌套向量中断控制器(NVIC)最多能提供240个物理中断、1个不可屏蔽中断(NMI)和各种系统异常,每一个中断都分配一个中断优先级(共 256个优先级),可动态调整。NVIC 可支持嵌套中断,处理中断时,程序计数器、程序状态寄存器、链接寄存器和通用寄存器自动压入堆栈,中断处理完成后再由硬件自动恢复这些寄存器的内容,无须任何软件干预。
②M3 的特点
Cortex-M3 处理器集成度高、芯片空间使用合理、低成本、低功耗,是专业嵌入式应用很好的选择
③CM4 和CM3的区别
CM4比CM3多一个VFP可选部件,具有数字信号处理能力。
考点8 ARM Cortex实时嵌入式处理器
(1)Cortex-R 的介绍。
Cortex-R属于中档处理器,它提供的性能比 Cortex-M系列高得多,而 Cortex-A 系列则性能更高,专用于需要运行复杂操作系统的面向用户的应用。Cortex-R处理器系列有 Cortex-R4、Cortex-R5和 Cortex-R7等品种,适用于计算复杂、实时性要求苛刻的领域。
(2)Cortex-R的主要特点
①高性能
采用多级流水线结构,时钟频率较高,具有高性能DSP和硬件 SIMD,可快速执行复杂代码和数字信号处理功能。
②)实时处理
中断响应快,片内紧耦合存储器(Tightly Coupled Memory,TCM)能快速存取代码/数据,给实时系统的响应速度和高吞吐量的操作提供了保障。
③安全
内存保护单元(MPU)支持用户模式和授权软件模式,存储器和总线采用错误检测与纠正(Error CorrectingCode,ECC)技术,可双内核几余配置,保证系统运行可靠。
④低成本
通过配置/排除某些功能使能效和芯片面积/成本效益最佳,调试断点和检测点可进行快速开发和测试,加快上市速度和可定制功能。
(3)Cortex-R的结构
以Codex-R4为例,其核心是采用ARMV7-R架构的处理器核 ARMR4,它支持ARM/Thumb-2指令集,代码密度高;使用硬件实现单指令多数据(SingleInstruction Multiple Data,SIMD)的DSP指令;具有可选的浮点运算器(处理器型号为Cortex-R4F);使用8级流水线技术实现。
考点9 ARM Cortex 应用处理器
(1)Cortex-A 的应用领域
Cortex-A处理器系列适用于有高计算要求、需运行功能丰富的操作系统以及要求提供交互媒体和图形显示的应用领域。
(2)Cortex-A 处理器的架构
Cortex-A处理器除了A50系列为64位字长,采用ARMV8A 架构外,其他均为32 位字长,包括Corex-A17/A15/A12/A9/A8/A7/A5处理器,它们使用基于ARMV7A架构的处理器核,支持传统的 ARM、Thumb指令集和高性能紧凑型 Thumb-2EE指令集,具有完全的应用兼容性;提供Java 字节码加速执行的Jazelle 技术,提供可信计算的 Trust Zone 安全扩展;采用最多可达13级的深度流水线技术,处理器时钟频率可达2GHz 左右;Codex-A处理器中都集成了浮点运算器VFP,提供了高性能的单精度和双精度浮点运算:集成了多媒体处理引擎 NEON,提供了对于高级 SIMD指令的支持:包含有分开的指令Cache和数据Cache(有些还包含二级 Cache),实现了哈佛存储结构。有些处理器还支持 ARMV7A 架构的扩展,支持更大的物理地址访问、硬件虚拟化和 128位的 AMBA4 ACE 总线。
考点10 ARM 处理器的工作状态及工作模式
(1)ARM 处理器工作状态及其切换
在 ARM的体系结构中,处理器可以工作在3种不同的状态,一是 ARM 状态,二是Thumb 状态及 Thumb-2状态,三是调试状态。
①ARM 状态
ARM 状态是 ARM 处理器工作于32位指令的状态,即32位状态,所有指令均为32位宽度
②Thumb 状态
Thumb 状态是 ARM 执行 16 位指令的状态,即 16 位状态。在 Thumb 模式下,指令代码只有 16 位,使代码密度变大,占用内存空间减小,提供比32位程序代码更佳的效能。但在有些情况下如异常处理时必须执行 32位 ARM 状态下的 ARM 指令,如果原来工作于 Thumb 状态,必须将其切换到 ARM 状态。
对于具有 Thumb-2指令集的处理器,Thumb 状态就是运行 Thumb-2指令的工作状态
a.除 Cortex_M 系列处理器外,所有 ARM 处理器复位后开始执行代码时总是只处于 ARM 状态。如果需要则可通过下面的方法切换到 Thumb 状态。
b.Cortex-M 处理器因为只有 Thumb-2指令集,所以只有 Thumb 状态和调试状态两种。
③调试状态
处理器停机调试时进入调试状态。
④ARM与Thumb 间的切换
a.由ARM 状态切换到 Thumb 状态
通过 BX指令,将操作数寄存器的最低位设置为1即可将 ARM 状态切换到 Thumb 状态。如果 RO[0]=1,则执行 BX R0 指令将进入 Thumb 状态。
如果 Thumb 状态进入异常处理(异常处理要在 ARM 状态下进行),则当异常返回时,将自动切换到 Thumb状态。
b.由 Thumb 状态切换到 ARM 状态。
通过 BX指令,将操作数寄存器的最低位置为0即可将 Thumb 状态切换到 ARM 状态。如果 RO[0]=0,则执行 BX R0 指令将进入 ARM 状态。
当处理器进行异常处理时,则从异常向量地址开始执行,将自动进入ARM 状态。
(2)RAM 处理器的工作模式
体系结构(除Cortex 外)支持7种工作模式,取决于当前程序状态寄存器CPSR的低5位的值。
工作模式 | 功能说明 | 可访问的寄存器 | CPSR 「M4:MO] |
用户模式 User | 程序正常执行工作模式 | PC,R14~RO,CPSR | 10000 |
快速中断模式FQ | 处理高速中断,用于高速数据传输或通道处理 | PC,R14_fiq~R8_fiq,R7~RO,CPSR,SPSR_fiq | 10001 |
外部中断模式IRO | 用于普通中断处理 | PC,R14_irq~R13_irq,R12~RO,CPSR,SPSR_irg | 10010 |
管理模式SVC | 操作系统的保护模式,处理软中断SWI | PC,R14_svc~R13_svc,R12~RO,CPSR,PSR_svc | 10011 |
中止模式ABT | 处理存储器故障,实现虚拟存储器和存储器保护 | PC,R14 abt~R13 abt, R12~RO,CPSR,SPSR abt | 10111 |
未定义指令模式UND | 处理未定义的指令陷阱,用于支持硬件协处理器仿真 | PC,R14_und~R13_und,R12~RO,CPSR,SPSR_ und | 11011 |
系统模式SYS | 运行特权级的操作系统任务 | PC,R14~RO,CPSR | 11111 |
ARM 处理器工作模式间可以相互转换,但是是有条件的。当处理器工作于用户模式时,除非发生异常,否则将不能改变工作模式。当发生异常时,处理器自动改变 CPSR[M4∶M0]的值,进入相应的工作模式。
考点11 ARM 处理器的寄存器组织
(1)ARM 状态下的寄存器组织
ARM 处理器共有37个寄存器,包括31个通用寄存器(含PC)和6个状态寄存器。工作于ARM状态下,在物理分配上寄存器被安排成部分重叠的组,每种处理器工作模式使用不同的寄存器不同模式下的寄存器组如图所示。
ARM 处理器工作在不同模式时使用的寄存器有所不同,但其共同点是:
一是无论何种模式,R15均作为PC使用;
二是CPSR为当前程序状态寄存器:
三是R0~R7为公用的通用寄存器。
不同之处在于高端7个通用寄存器和状态寄存器在不同模式下不同。
①通用寄存器
通用寄存器中不分组的寄存器共8个:RO~R7:R8~R12共2组计10个寄存器,标有fq的寄存器代表快速中断模式专用,与其他模式地址重叠但寄存器内容并不冲突;R13~R14除了用户模式和系统模式分别为堆栈指针(Stack Pointer,SP)和程序链接寄存器(Linkregister,LR)之外,其他模式下均有自己独特的标记方式,是专门用于特定模式的寄存器,共6组计12个。加上作为PC的R15,这样通用寄存器共31个。所有通用寄存器均为 32 位结构。
②状态寄存器
状态寄存器共6个,除了共用的当前程序状态寄存器CPSR外还有分组的备份程序状态寄存器SPSR(5组共5个)。程序状态寄存器的格式如图所示。
图中条件码标志有4个,为N、Z、C和V,Q标志以及8个控制位为I、F、T、M4~MO。
a.条件码标志含义
N为符号标志,N=1表示运算结果为负数,N=0表示运算结果为正数,Z为全0标志,运算结果为0,则Z=1,否则Z=0。
C为进借位标志,加法有进位时C=1,无进位时 C=0:减法有借位时C=0,无借位时 C=1。要注意这里的减法借位标志与x86等常规定义有区别。
V为溢出标志,加减法运算结果有溢出时V=1,否则V=0。
Q 为增强的 DSP 运算指令是否溢出的标志,溢出时 Q=1,否则 Q=0。
b.控制位含义
I为中断禁止控制位,I=1禁止外部IRQ 中断,I=0 允许 IRQ 中断。
F为禁止快速中断 FIQ 的控制位,F=1 禁止 FQ 中断,F=0 允许 FIQ 中断。
T为 ARM与Thumb指令切换,T=1 时执行 Thumb 指令,否则执行 ARM 指令。应注意的是,对于不具备Thumb 指令的处理器,T=1时表示强制下一条执行的指令产生未定义的指令中断。
M4~M0为模式选择位,决定处理器工作于何种模式。
CPSR 状态寄存器可分为4个域:标志域F(31:24)、状态域S(23:16)、扩展域X(15:8)和控制域C(7:0)。使用单字节的传送操作可以单独访问这4个域中的任何一个,如CPSRC、CPSRF,这样可以仅对这个域操作而不影响其他位。
(2)Thumb 状态下的寄存器组织
Thumb状态下的寄存器组是ARM状态下寄存器组的子集,Thumb/Thumb2状态下的寄存器组如图所示。
高位寄存器R8~R12在 Thumb 状态下不可见,即不能直接作为通用寄存器使用,而在Thumb-2下可以使用,即R8~R12只有在32位指令状态下才可当作通用寄存器使用。
(3)带MMU的ARM 处理器中的控制寄存器
对于内置 MMU的 ARM 处理器,存储管理涉及虚拟存储技术,采用相关页表的技术来访问内存,其控制寄存器为 CP15,由它控制 C0~C15共16个系统控制寄存器,每个寄存器包括若干非常复杂的操作功能。
考点12 ARM处理器的异常
(1)异常的定义
异常(Exceptions)是由于内部事件或外部事件引起的请求,使处理器去做相应处理的事件。当发生异常时,系统执行完当前指令后,跳转到相应的异常处理程序入口执行异常处理,异常处理完毕后程序返回。
(2)ARM异常种类、异常向量表及优先级
①ARM 异常种类
在 ARM 体系结构(除 Codex 外)中,异常用来处理软中断、未定义指令陷阱、系统复位及外部中断。共有7种不同类型的异常,它们的优先级及其对应的向量地址如表所示。
②ARM 异常向量
异常向量的地址由 32位地址空间的低端正常地址范围0x00000000-0x0000001F决定。 ARM 处理器片内其他硬件组件的中断使用 IRO 或 YIQ。
③ARM 异常的优先级
7种类型的异常分成6级,级别最高的是复位,最低的是未定义的指令UND或软件中断SWI。其中 UND和 SWI异常(包括协处理器不存在异常)是互斥的,不可能同时发生,因此优先级是相同的,并不矛盾。复位异常的优先级最高,因此在任何情况下只要进入复位状态,系统便无条件地将PC指向0x00000000处去执行系统的第一条指令。通常此处放一条无条件的转移指令,转移到系统初始化程序处。
(3)ARM异常的中断响应过程
发生异常后,除了复位异常立即中止当前指令之外,其余情况都是处理器完成当前指令后才去执行异常处理程序。ARM处理器对异常的响应过程如下:
①将 CPSR 的值保存到将要执行的异常中断对应的各自 SPSR 中,以实现对处理器当前状态、中断屏蔽及各标志位的保护。
②设置当前状态寄存器 CPSR的相应位:设置CPSR中的M4~M0的5个位,进入相应工作模式,设置I=1禁止IRO 中断,如果进入复位模式或FIQ 模式,还要设置F=1以禁止 FIQ 中断。
③将引起异常指令的下一条地址(断点地址)保存到新的异常工作模式的LR(R14)中,使异常处理程序执行完后能正确返回原来的程序处继续向下执行。
④给程序计数器 PC强制赋值,转入由表 2-4所示的向量地址,以便执行相应的处理程序。每种异常模式对应两个寄存器SP(R13_mode)和LR(R14_mode),mode为SVC、irg、und、fiq 或 abt之分别存放堆栈指针和断点地址。
(4)从异常处理程序中返回
复位异常处理程序执行完无需返回。其他所有异常处理完毕后必须返回到原来程序处继续向下执行。
返回步骤:
a.恢复原来被保护的用户寄存器。
b.将 SPSR-mode 寄存器值复制到 CPSR 中,使得原先的 CPSR 状态从相应的 SPSR 中恢复,以恢复被中断的程序工作状态。
c.根据异常类型将PC值恢复成断点地址,以继续执行用户原来运行着的程序。
d.清除CPSR 中的中断禁止标志I和F,开放外部中断IRO 和快速中断 FIO。
应该注意的是,程序状态字及断点地址的恢复必须同时进行。
考点13 ARN的存储器格式要求及数据类型
(1)ARM的两种存储字的格式
①大端模式
32 位数据字的高字节存储在低地址中,而数据字的低字节则存放在高地址中。
②小端模式
与大端模式存储数据完全不同,在小端模式下,32位数据字的高字节存放在高地址,而低字节存放在低地址。
系统复位时一般自动默认为小端模式。
(2)ARM存储器的数据类型
①6 种数据类型
除 Cortex-A50 外,32位 ARM 处理器中支持字节(8位)、半字(16位)、字(32位)3 种数据类型,其中字需要4字节对齐(地址的低两位为0),半字需要2字节对齐(地址的最低位为 0)。其中每一种又支持有符号数和无符号数,因此认为共有6种数据类型。
②边界对齐
ARM 微处理器的指令长度可以是32位(在ARM状态下),也可以为16位(在Thumb 状态下)。
③其他数据类型
ARM 还支持其他类型的数据,如浮点数等数据类型等。
考点14 ARM 处理器中的 MMU 和 MPU
(1)ARM处理器中的MMU
①虚拟存储器技术
借助于 ARM 处理器中的MMU部件,能把系统中不同类型的存储器(如Fash、SRAM、SDRAM、ROM、优盘等)进行统一管理,通过地址映射,使需要运行在连续地址空间的软件可运行在不连续的物理存储器中,需要较大存储空间的软件可以运行在较小容量的物理存储器中,这就是虚拟存储器技术。使用虚拟存储器的另一个优点是,它还提供了对存储器的存取保护,在多任务系统中这些都是非常重要的。
②)MMU 的功能
a.虚拟地址到物理地址映射
ARM 中 MMU 功能可以被“禁止”或“使能”。当“使能”MMU后,ARM 处理器产生的地址是虚拟地址。虚拟地址空间分成若干大小固定的块,称为页,物理地址空间也划分为同样大小的页。
MMU的功能就是进行虚拟地址到物理地址的转换,这需要通过查找页表来完成。页表是一张虚拟地址与物理地址的对应表,页表存储在内存储器中。在ARM 系统中,使用协处理器CP15中的寄存器C2保存页表在内存中的起始地址(基地址)。从虚拟地址到物理地址的映射关系示意如图所示。
b.存储器访问权限控制
存储器的访问权限可以以块(页)为单位进行设置,分为不可访问、只读、可读/写等不同的权限。当访问具有不可访问权限的页时,会产生一个存储器异常的信号通知ARM 处理器。
③存储器访问的顺序
当执行加载/存储指令要访问存储器时,MMU 先查找 TLB 中的转换表。如果 TLB 中没有,则硬件会自动查找主存储器内的页表,找到虚拟地址到物理地址的转换信息和访问权限信息就可以用来进行存储器的读/写操作,同时把这些信息放入 TLB 中供此后继续使用。如果在页表中也找不到转换信息,则产生中断,通知 OS 进行处理。
④TLB 中信息的用途
a.访问权限控制信息用来控制访问是否被允许。
b.对没有高速缓存(指令Cache和数据Cache)的系统,装换得到的物理地址将被用作访问主存器的地址。
(2)ARM处理器中的MPU
①简介
存储器保护单元(MPU)是对存储器进行保护的可选组件。它提供了简单替代 MMU 的方法来管理存储器
②)MPU 的域
MPU允许 ARM 处理器的4GB的地址空间定义8对域,分别控制8个指令和8个数据内存区域。每个域的首地址和界(或长度)均可编程。MPU中一个区域是一些属性值及其对应的一片内存。这些属性包括起始地址、长度、读/写权限缓存等。带 MPU的 ARM 处理器使用不同的域来管理和控制指令内存和数据内存。域和域可以重叠并且可以设置不同的优先级,域的起始地址必须是其大小的整数倍。域的大小可以是4KB到4GB之间任意一个2的指数。
考点15 ARM 指令分类及指令格式
ARM 指令集使用标准的、固定长度的 32位指令格式,所有 ARM 指令都使用4位的条件编码来决定指令是否执行,以解决指令执行的条件判断。
(1)ARM 指令分类
ARM 微处理器的指令集可以分为分支指令、数据处理指令、程序状态寄存器(CPSR)处理指令、加载/存储指令、协处理器指令和异常产生指令六大类。
(2)ARM 指令格式
①指令一般格式
<opcode>{<cond>}{S} <Rd>,<Rn>{,<op2>}
其中<>为不可省,{}为可省略,opcode、cond 与S之间没有分隔符,{S)与 Rd之间用空格隔开。格式中具体项目的含义如表所示。
关于#imm8m的说明:
a.对于 ARM 指令集,#imm8m表示一个由8位立即数经循环右移任意偶数位次形成的 32 位操作数。
b.对于 Thumb指令集,#imm8m表示一个由8位立即数经左移任意位次形成的 32 位操作数。
②指令的条件域
在 ARM 状态时,几乎所有的指令均根据 CPSR 中条件码的状态和指令的条件域有条件地执行。当指令的执行满足条件时,指令被执行,否则指令被忽略。
每一条 ARM 指令包含4位的条件码,位于指令的最高4位[31:28]。条件码共有16种,每种条件码可用两个字符表示,这两个字符可以添加在指令助记符的后面与指令同时使用。
在16种条件码中,只有15种可以使用,如表 所示,第16种(1111)为系统保留,暂时不能使用。通常使用CMP指令产生条件标志。
(3)ARM指令中操作数符号
①“#” 立即数符号,其后是十进制数或十六进制数。
②“0x” 十六进制符号,“0x”后面的数据(每位可以是 0~9、A~F)表示十六进制数。
③“!” 更新基址寄存器符号,“!”符号表示指令在完成操作后最后的地址应该写入基址寄存器中。
④)“^” 复制 SPSR 到CPSR 符号,“^”符号用于批量数据存储指令中放在寄存器之后作为后缀,当其前面的寄存器不包含PC时,该符号表示所用的寄存器是用户模式的寄存器:当其前面的寄存器包含PC时,该符号指示将SPSR寄存器的值复制到CPSR寄存器中。
⑤“_” 指示寄存器列表范围符号,在有些指令中,表示多个连续寄存器(寄存器列表).
(4)ARM指令中的移位操作符
①移位操作的使用限制
移位操作在 ARM 指令集中不作为单独的指令使用,它只能在指令格式中作为一个字段,在汇编语言中表示为指令中的选项。
②移位操作的类型
移位操作包括如下6种类型:
LSL(逻辑左移)、ASL(算术左移)、LSR(逻辑右移)、ASR(算术右移)ROR(循环右移)以及RRX(带扩展的循环右移)。
③通用寄存器进行移位操作的格式
Rm,<opsh>#<shift>
其中,Rm为要移位的通用寄存器;<opsh>为移位操作符,包括LSL、ASL、LSR、ASR、ROR及RRX;<shif>为移位次数(0~31)。
考点16 ARM 指令的寻址方式
(1)立即寻址
立即寻址也称立即数寻址,操作数本身就在指令中给出,只要取出指令也就取到了操作数。这个操作数被称为立即数。如以下指令:
MOV RO,#0x12 ;RO=0x12
ADC RO,RO,#100 ;RO←RO+100+C
(2)寄存器寻址
寄存器寻址就是利用寄存器中的数值作为操作数。如以下指今:
ADD RO,R1,R2 ;RO←R1+R2
该指令的执行效果是将寄存器R1和R2的内容相加,其结果存放在寄存器RO中。
(3)寄存器间接寻址
寄存器间接寻址就是以寄存器中的值作为操作数地址,而操作数本身存放在存储器中。用于间接寻址的寄存器必须用П括起来。如以下指令:
LDR RS,[R4] ;R5←[R4],间接寻址的寄存器是R4
STR RI,[R2] ;[R2]-R1,间接寻址的寄存器是R2
第1条指令是将以R4的值为地址的存储器中的数据传送到R5中。第2条指令是将R1的值传送到以R2的值为地址的存储器中。
(4)基址加变址寻址基址加变址寻址就是将寄存器(该寄存器一般称作基址寄存器)的内容与指令中给出的地址偏移量相加,从而得到一个操作数的有效地址。变址寻址方式常用于访问某基地址附近的地址单元。采用变址寻址方式的指令常见的有如下几种形式:
LDR RO,[R1,#4] ;RO←[R1+4]
将寄存器R1的内容自动增加 4,形成操作数的有效地址,从中取得 32位操作数存入寄存器 RO中。
STR RI,[R2, #8] ;[R2+8]←R1
将寄存器RI的32位操作数存储到R2+8指示地址开始的存储区域中。
LDR RO,[R1,#4]! ;RO←[R1+4]、R1←R1+4
将寄存器 R的内容自动增加4形成操作数的有效地址,从中取得32位操作数存入寄存器RO中,然后R1的内容自增4。符号“!”表示指令在完成数据传送后应该更新基址寄存器。
LDR RO,[R1],#4 ;RO←[R1]、R1←R1+4
以寄存器R1的内容作为操作数的有效地址,从而取得操作数存入寄存器RO中,然后R1的内容自动增加 4。
LDR RO,[R1.R2] ;RO←[R1+R2]
将寄存器R1的内容加上寄存器R2的内容形成操作数的有效地址,从而取得操作数存入寄存器 RO中。
STR RO,「RI. R2] ;[R1+R2]←RO
将寄存器RO的内容存储到由R1+R2指示的有效地址对应的存储单元中。
(5)相对寻址
相对寻址以程序计数器 PC的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。
BL Subrouhtine_A ;跳转到子程序Subrouhtine_A处执行
...
Subrouhtine_A
...
MOV PC,LR ;从子程序返回
(6)堆栈寻址
堆栈指针是一个专用寄存器,用来指示当前的操作位置,堆指针总是指向栈顶。当堆栈指针指向最后压入堆栈的数据时,称为满堆栈(Ful Stack),而当堆栈指针指向下一个将要放入数据的空位置时,称为空堆栈(EmptyStack)。
当堆栈由低地址向高地址生成时,称为递增堆栈:当堆由高地址向低地址生成时,称为递减堆栈。①满递增堆栈
堆栈指针指向最后压入的数据,且由低地址向高地址生成。
②满递减堆栈
堆栈指针指向最后压入的数据,且由高地址向低地址生成。
③空递增堆栈
堆栈指针指向下一个将要放入数据的空位置,且由低地址向高地址生成。
④空递减堆栈
堆栈指针指向下一个将要放入数据的空位置,且由高地址向低地址生成。
(7)块拷贝寻址
块拷贝寻址又称多寄存器寻址,采用多寄存器寻址方式,一条指令可以完成多个寄存器值的传送。这种寻址方式可以用一条指令完成传送最多16个通用寄存器的值。如以下指令:
LDMIA R0,[R1,R2,R5,R9] ;R1 ← [R0]、R2 ← [R0+4]、R5 ← [R0+8]、R9 ← [R0+12]
考点17 ARM 指令集
(1)数据处理类指令
①数据处理类指令的分类
a.数据传送指令
用于在寄存器和存储器之间进行数据的双向传输:
b.算术逻辑运算指令
完成常用的算术与逻辑的运算,该类指令不但将运算结果保存在目的寄存器中,同时更新CPSR 的相应条件标志位:
c.比较指令
不保存运算结果,只更新CPSR中相应的条件标志位。
②)数据处理类指令
(2)程序状态寄存器访问指令
①程序状态寄存器访问指令的作用
程序状态寄存器访问指令,用于在程序状态寄存器和通用寄存器之间传送数据。
②)MRS--程序状态寄存器到通用寄存器的数据传送指令
格式:MRS{cond}Rd,<PSR> ;PSR可以是CPSR或SPSR
用途:MRS指令用于将程序状态寄存器的内容传送到通用寄存器中。该指令一般用在以下情况:
a.当需要改变程序状态寄存器的内容时,可用 MRS将程序状态寄存器的内容读入通用寄存器,修改后再写回程序状态寄存器。
b.当在异常处理或进程切换时,需要保存程序状态寄存器的值,可先用该指令读出程序状态寄存器的值,然后保存。
③MSR--通用寄存器到程序状态寄存器的数据传送指令
格式:MSR{cond}<PSR>_<fields>,Rm:PSR可以是CPSR或SPSR,fields为域
用途:MSR 指令用于将操作数的内容传送到程序状态寄存器的特定域中。其中,操作数可以为通用寄存器或立即数。<felds>域用于设置程序状态寄存器中需要操作的位,32位的程序状态寄存器可分为4个域:
PSR[31:24]为条件标志位域,用f表示,f为小写。
PSR「23:16]为状态位域,用s表示,s为小写。
PSR[15:8]为扩展位域,用x表示,x为小写。PSR[7:0]为控制位域,用c表示,c为小写。该指令通常用于恢复或改变程序状态寄存器的内容,使用时一般要在 MSR 指令中指明将要操作的域。
(3)分支指令
①分支指令的作用
分支指令用于实现程序流程的跳转。在ARM程序中有两种方法可以实现程序流程的转移:一是使用专门的跳转指令,二是直接向程序计数器PC写入跳转地址值。
通过向程序计数器PC写入跳转地址值,可以实现在4GB的地址空间中的任意跳转。在跳转之前结合使用MOVLR,PC等类似指令,可以保存将来的返回地址值,从而实现在4GB连续的线性地址空间的子程序调用。
ARM 指令集中的分支指令可以完成从当前指令向前或向后的32MB的地址空间的跳转。
②B--转移指令
格式:B {cond} Label:Label为目标地址格式
用途:B指令是最简单的跳转指令。一旦遇到一个B指令,ARM 处理器将立即跳转到给定的目标地址,从那里继续执行。注意,存储在跳转指令中的实际值是相对当前 PC 值的一个偏移量,而不是一个绝对地址,它的值由汇编器来计算(参考寻址方式中的相对寻址)。它是24位有符号数,左移两位后有效偏移为26位(前后32MB的地址空间,即+32MB)。
注意:如果使用指令:B.:这里的“。"表示当前地址,本条指令执行的效果是自循环,即进入死循环以等待系统复位,等于LabelBLabel.
③BX--带状态切换的转移指令
格式:BX{cond} <Rn>
用途:BX指令跳转到指令中所指定的由寄存器Rn与OxFFFFFFFE 相与后的结果指示的目标地址(即Rn[0并不作为目标地址,而是作为状态切换位),目标地址处的指令既可以是ARM指令,也可以是Thumb指令。如果 Rn中的最低位Rn「0]=1则指令将 CPSR 的T标志置1,且将目标地址的代码解释为Thumb(状态切换到
Thumb 指令集)。
④BL--带返回的转移指令
格式:BL {cond} Label
用途:BL是带返回的跳转指令,在跳转之前,会在寄存器R14中保存PC的当前值。因此,可以通过将 R14的内容重新加载到PC中,以返回到跳转指令之后的那个指令处执行。该指令是实现子程序调用的一个基本且常用的手段。
⑤BLX--带返回且带状态切换的转移指令
格式:BLX 目标地址
用途:BLX指令从 ARM指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由ARM 状态切换到 Thumb 状态,该指令同时将 PC的当前内容保存到寄存器 R14中。因此,当子程序使用Thumb 指令集,而调用者使用 ARM 指令集时,可以通过 BLX 指令实现子程序的调用和处理器工作状态的切换。同时,子程序的返回可以通过将寄存器 R14 值复制到 PC 中来完成。
(4)加载/存储指令
①加载/存储指令的作用和分类
用于在寄存器和存储器之间传送数据。加载指令用于将存储器中的数据传送到寄存器,存储指令用于将寄存器中的数据传送到存储器。
加载/存储指令有三类:单一数据加载/存储、批量数据加载/存储以及数据交换指令。
②单一数据加载/存储指令
a.LDR--字数据加载指令
用途:LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。当程序计数器 PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。
b.LDRB-字节数据加载指令
用途:LDRB指令用于从存储器中将一个8位的字节数据传送到目的寄存器中,同时将寄存器的高 24位清零。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。
c.LDRH--半字数据加载指令
用途:LDRH指令用于从存储器中将一个16位的半字数据传送到目的寄存器中,同时将寄存器的高16位洁零。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。
d.STR--字数据存储指令
用途:STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。该指令在程序设计中比较常用,且寻址方式灵活多样,使用方式可参考指令LDR。
e.STRB--字节数据存储指令
用途:STRB指令用于从源寄存器中将一个8位的字节数据传送到存储器中。该字节数据为源寄存器中的低8位。
f.STRH-半字数据存储指令
用途:STRH指令用于从源寄存器中将一个16位的半字数据传送到存储器中。该半字数据为源寄存器中的低 16 位。
③批量数据加载/存储指令ARM 微处理器所支持的批量数据加载/存储指令可以一次在一片连续的存储器单元和多个寄存器之间传送数据。
a.LDM--批量数据加载指令
格式:LDM { 条件} {类型} 基址寄存器{ ! },寄存器列表{ ^ }
用途:LDM 指令用于将由基址寄存器所指示的一片连续存储器读到寄存器列表所指示的多个寄存器中,该指令的常见用途是将多个寄存器的内容出栈。
b.STM--批量数据存储指令
用途:STM 指令用于将寄存器列表所指示的多个寄存器的数据存储到基址寄存器所指示的一片连续存储器中,该指令的常见用途是将多个寄存器的内容入栈
(5)协处理器指令
①协处理器指令的特点
ARM 微处理器可支持多达16个处理器,用于各种协处理操作在程序执行的过程中,每个协处理器只执行针对自身的协处理器指令,忽略 ARM 处理器和其他协处理器的指令。
②协处理器指令的作用
ARM 的协处理器指令主要用于 ARM 处理器初始化 ARM 协处理器的数据处理操作,在 ARM 处理器的寄存器和协处理器的寄存器之间传送数据,以及在ARM 协处理器的寄存器和存储器之间传送数据。
③协处理器指令
ARM 协处理器指令包括5条:CDP(协处理器数据操作指令)、LDC(协处理器数据加载指令)、STC(协处理器数据存储指令)、MCR(ARM处理器寄存器到协处理器寄存器的数据传送指令)以及MRC(协处理器寄存器到 ARM 处理器寄存器的数据传送指令)。
(6)异常中断指令
①SWI--软件中断指令
格式:SWI {cond} imm24; imm24为24位立即数
用途:SWI指令用于产生软件中断,以便用户程序能调用操作系统的系统例程。操作系统在SWI的异常处理程序中提供相应的系统服务,指令中24位的立即数指定用户程序调用系统例程的类型,相关参数通过通用寄存器传递,当指令中 24位的立即数被忽略时,用户程序调用系统例程的类型由通用寄存器RO的内容决定,同时,参数通过其他通用寄存器传递。
②BKPT--断点中断指令
格式:BKPT imm16; imm16为16位立即数
用途:BKPT指令产生软件断点中断,可用于程序的调试。16 位立即数用于保存软件调用中额外的断点信息。
考点18 Thumb 指令集
(1)Thumb指令集和 ARM 指令的关系
①Thumb 指令集是 ARM 指令系统的一个子集,允许指令编码为 16 位的长度。与等价的 32 位代码相比较,Thumb指令集在保留32位代码优势的同时,大大节省了系统的存储空间。
②所有的 Thumb 指令都有对应的 ARM 指令,而且 Thumb 的编程模型也对应于 ARM 的编程模型,在应用程序的编写过程中只要遵循一定的调用规则,Thumb 子程序和 ARM 子程序就可以互相调用。
a.当处理器在执行 ARM 程序段时,称ARM 处理器处于ARM 工作状态:
b.当处理器在执行 Thumb 程序段时,称 ARM 处理器处于 Thumb 工作状态。
③大多数 Thumb 指令是无条件执行的,而几乎所有的 ARM 指令都是有条件执行的;大多数的 Thumb 数据处理指令的目的寄存器与其中一个源寄存器相同。
(2)Thumb中的单一寄存器加载/存储指令
单一寄存器加载/存储指令,Thumb只能访问内部通用寄存器R0~R7。多寄存器加载/存储指令,Thumb 指令集是采用PUSHIPOP来实现的,指令执行时以 R13 为堆栈指针,其内容为基地址,实现满递增递减堆栈。除可加载/存储 RO~R7外,PSUH指令还可以存储链接寄存器LR(R14),POP指令可以加载程序计数器 PC(R15)。
考点19 ARM 处理器支持的伪指令
(1)ADR 伪指令
格式:ADR {cond} Rd,expr
用途:ADR指令用于相对偏移地址加载到通用寄存器中。
(2)LDR 伪指令
格式:LDR {cond} Rd,=[expr | label-expr]
用途:LDR 指令用于一个32位常数的加载或地址的加载。
使用 LDR 伪指令有两个目的:
①当用 MOV或 MNV 指令无法加载符合要求的 32 位立即数时,可用 LDR 伪指令加载任意 32 位操作数到寄存器。因为MOV或MNV指令加载的32位数据只能是8位立即数通过移位的方式得到的,所以不能加载任意 32 位常数,如0x12345678这样的操作数不能用MOV指令完成。
②当需要程序的相对偏移地址或外部地址加载到寄存器时可使用LDR 伪指令。
(3)NOP空操作
格式:NOP
用途:产生所需的 ARM 无操作代码,用于简单延时,与MOVRd,Rd等效:
考点20 ARM 汇编器所支持的伪指令
(1)伪指令和伪操作的概念和作用
①概念
在 ARM 汇编语言程序中,有一些特殊指令助记符。这些助记符与指令系统的助记符不同,没有相对应的操作码,称这些特殊指令助记符为伪指令,它们所完成的操作称为伪操作。
②作用
伪指令在源程序中的作用是为完成汇编程序作各种准备工作,这些伪指令仅在汇编过程中起作用,一旦汇编结束,伪指令的使命就完成。伪指令一般与编译程序有关在不同的编译环境下有不同的编写形式和规则。RealView MDK使用很广,支持所有 ARM 处理器。而 ADS 和 MDK 使用同样的汇编工具armasm、链接工具 armlink,因此这部分主要介绍基于ammasm 汇编器的伪指令及程序设计。
(2)常用伪指令
考点21 ARM汇编语言的语句格式
(1)ARM 汇编语言的语句格式及说明
ARM(Thumb)汇编语言的语句格式为:{标号 } {指令或伪指令} ;{注释}
在汇编语言程序设计中,每一条指令的助记符可以全部用大写或全部用小写,但不允许在一条指令中大小写混用。在行的末尾用“\”表示下一行与本行为同一条语句。此外标号必须顶格写,不允许前面有空格。
ARM 汇编语言的标号后面是没有“:”的。
(2)在汇编语言程序中常用的符号
①符号的命名的规则
a.符号区分大小写,同名的大小写符号会被编译器认为是两个不同的符号。
b.符号在其作用范围内必须唯一。
c.自定义的符号名不能与系统的保留字相同。
d.符号名不应与指令或伪指令同名。
②)变量
程序中的变量是指其值在程序的运行过程中可以改变的量。
a.数字变量用于在程序的运行中保存数字值,但需注意数字值的大小不应超出数值变量所能表示的范围。
b.逻辑变量用于在程序的运行中保存逻辑值,逻辑值只有两种取值情况:真或假。
c.字符串变量用于在程序的运行中保存一个字符串,但注意字符串的长度不应超出字符串变量所能所能表示的范围。
③常量程序中的常量是指其值在程序的运行过程中不能被改变的量。
a.数字常量一般为32位的整数,当作为无符号数时其取值范围为0~;当作为有符号数时其取值范围为~。
b.逻辑常量只有两种取值情况:真或假。
c.字符串常量为一个固定的字符串,一般用于程序运行时的信息提示。
④变量代换
程序中的变量可通过代换操作取得一个常量。代换操作符为“S”。
a.如果在数值变量前面有一个代换操作符“S”,编译器会将该数字变量的值转换为十六进制的字符串,并将该十六进制的字符串代换“$”后的数字变量。
b.如果在逻辑变量前面有一个代换操作符“S”,编译器会将该逻辑变量代换为它的取值(真或假)。
c.如果在字符串变量前面有一个代换操作符“S”,编译器会将该字符串变量的值代换“$”后的字符串变量。
(2)汇编语言程序中的表达式和运算符
在汇编语言程序设计中,也经常使用各种表达式。表达式一般由变量、常量、运算符和括号构成。
①表达式运算优先级
a.优先级相同的双目运算符的运算顺序为从左到右。
b.相邻的单目运算符的运算顺序为从右到左,且单目运算符的优先级高于其他运算符
c.括号运算符的优先级最高。
②数值表达式及运算符
·数字表达式一般由数值常量、数值变量、数值运算符和括号构成。
a.算术运算符:+、-、*、/及 MOD
b.移位运算符:ROL、ROR、SHL及SHRb.
c.数值逻辑运算符:AND、OR、NOT及EOR
③逻辑表达式及运算符
·逻辑表达式一般由逻辑量、逻辑运算符和括号构成,其表达式的运算结果为真或假。
a.关系操作符:=、>、<、>=、<=、/=、<>
b.逻辑运算符:LAND、LOR、LNOT及LEOR
④字符串表达式及运算符
字符串表达式一般由字符串常量、字符串变量、运算符和括号构成。编译器所支持的字符串最大长度为 512B
a.返回字符串长度运算符:LEN
b.字节整数转换为字符运算符:CHR
c.字符串转换运算符:STR
d.返回左端字符串运算符:LEFT
e.返回右端字符串运算符:RIGHT
f.合并字符串运算符:CC
考点22 汇编语言的程序设计举例
(1)汇编程序的结构
①汇编源程序的结构
a.结构单位
在 ARM(Thumb)汇编语言程序中,以程序段为单位组织代码。段是相对独立的指令或数据序列,具有特定的名称。
b.段的分类
段可以分为代码段和数据段,代码段的内容为执行代码,数据段存放代码运行时需要用到的数据。一个汇编程序至少应该有一个代码段,当程序较长时,可以分割为多个代码段和数据段,多个段在程序编译链接时最终形成一个可执行的映像文件。
②)汇编可执行映像文件的结构
a.一个或多个代码段,代码段的属性为只读。
b.零个或多个包含初始化数据的数据段,数据段的属性为可读/写。
c.零个或多个不包含初始化数据的数据段,数据段的属性为可读/写。链接器根据系统默认或用户设定的规则,将各个段安排在存储器中的相应位置,因此源程序中段之间的相对位置与可执行的映像文件中段的相对位置一般不会相同。
③汇编源程序的示例
AREA Init,CODE,READONLY
ENTRY
Start
LDR RO,=0x3FF5000
MOVRI,#0xFF ;或LDR RI,=0xFF
STR RI,[RO]
LDR RO,=0x3FF5008
MOVR1,#0x01 ;或LDR R1,=0x01
STR RI,[RO]
...
END
(2)S3C2410系统引导程序代码
①系统引导程序的功能
a.关看门狗定时器,关中断
b.设置CPU速率及时钟频率
c.设置堆栈
d.切换用户模式并初始化用户堆栈
e.如果使用 DRAM 或其他设备,还要设置相关寄存器,初始化这些设备e.
f.初始化存储空间
g.跳转到C程序入口
②启动文件 Startup.S 及其代码分析
引导程序主要是一个启动代码文件Startup.S.
(3)顺序程序设计
①顺序程序设计的特点
顺序程序设计也称简单程序设计或直接程序设计,没有分支,也没有循环,是一条指令一条指令接下去执行程序结构。
(4)分支程序设计
①分支程序结构的实现方法
ARM 分支程序结构通常用分支指令B加上条件执行来实现。
②分支程序结构的实例
假如要把连续存放在内存区域0x30007000~0x30007008中的3个32位无符号数按递减次序排列,并在其后写入一个字节的标志 0xOD。为了实现排序操作,可以对3个数两两进行比较,比较后的大数放在前面,从而达到3个数按递减次序排列之目的。实现该算法的流程图如图所示。
(5)循环程序设计
①循环程序的作用
当需要重复执行某段程序时,可以利用循环程序结构。循环结构一般是根据某一条件判断为真或假来确定是否重复执行循环体。
②循环结构的程序的结构
a.循环初始部分--为开始循环准备必要的条件,如循环次数、循环体需要的初始值等。
b.循环体部分--重复执行的程序代码,其中包括对循环条件修改的程序段。
c.循环控制部分--判断循环条件是否成立,决定是否继续循环。其中,循环控制部分是编程的关键和难点。循环条件判断的循环控制可以在进入循环之前进行,即形成“先判断、后循环”的循环程序结构。如果循环条件判断的循环控制在循环之后进行,即形成“先循环、后判断”的循环程序结构。
③循环程序的实现原理
ARM 的循环程序控制通常用比较指令CMP、ADD或SUB等能产生条件的指令,然后用B加上条件分支来达到目的。对于先循环后判断的结构,首先用一个通用寄存器,如RO0作为循环次数计数器,在主循环体内对 R0减1操作,并判断R0是否为0,不为0则继续,为0则结束循环。
④由计数控制循环
用一个通用寄存器 Rn(n=0,1,2,3,4,5,6,7)作为计数器,先给初始值,然后每循环一次减 1,直到循环次数为0结束循环,程序结构如下:
MOV Rn ,#Counter ;循环体初始化部分
...
LPM ... ;循环体
SUBS Rn,Rn,#1 ;修改计数值
BCC LPM ;控制循环部分
或:
MOV Rn ,#Counter ;循环体初始化部分
...
LPM ... ;循环体
SUBRn,Rn,#1 ;修改计数值
CMPRn,#0 ;与0比较
BNE LPM ;控制循环部分
⑤由条件控制循环
有些情况是不能预先知道计数次数的,要通过一定的条件控制循环,这种情况的循环控制就要用到相关条件,通过相关条件控制循环是否结束。
例题:从Ox30500000开始的内存区域存放看若十字节的BCD码数据,开以0xOD 结束。编程对这些数据进行累加和计算,取累加和的前两个字节放到这个数据结束字符之后的两字节中,并把数据个数写入后一个单元中。
AREA EXAMPLE4,CODE,READONLY
ENTRY
CODE32
MYADD MOV R0,#0
MOV R1,#0
LDR R2, =0x30500000
LOPPA LDRB R3,[R2]
CMP R3,#0x0D
BNE LOPPOUT
ADD R1,R1,R3
ADD R2,R2,#1
ADD R0,R0,#1
B LOPPA
LOPPOUT STRH R1,[R2]
STR R0,[R2+2]
END
(6)子程序设计
①ARM 汇编语言子程序设计与x86的子程序设计的比较
相同点是都有一个子程序的名称,也有子程序的返回指令;不同点是ARM 汇编的返回不是RET等,采用MOVPC,LR返回。如果一个子程序不在调用的同一个文件中,则需要先用IMPORT 声明是外部的,否则无法正常调用该子程序。子程序在同一文件中无需声明。IMPORT声明可以放在AREA语句之前。
②ARM 汇编语言程序中子程序的调用
子程序的调用一般是通过 BL指令来实现的。在程序中,使用指令:BL 子程序名即可完成子程序的调用。该指令在执行时完成如下操作:将子程序的返回地址存放在链接寄存器LR中,同时将程序计数器PC指向子程序的入口点。当子程序执行完毕需要返回调用处时,只需将存放在LR中的返回地址重新拷贝给程序计数器PC。在调用子程序的同时,也可以完成参数的传递和从子程序返回运算结果,通常可以使用寄存器 RO~R3 完成。
考点23 嵌入式C语言与汇编语言混合程序设计
(1)汇编语言与C语言的混合编程的方式
①在汇编程序和C语言程序之间进行变量的互访。
②汇编程序、C 语言程序间的相互调用。
③在C语言代码中嵌入汇编指令。
(2)混合编程中各自的作用
在这3种混合编程技术中,必须遵守一定的调用规则,如物理寄存器的使用、参数的传递等。在实际的编程应用中使用较多的方式是程序的初始化部分用汇编语言完成,而主要的编程任务用C语言完成。程序在执行时首先完成初始化过程,然后跳转到C语言程序中。汇编程序和C语言程序之间一般没有参数的传递,也没有频繁的相互调用。
(3)混合调用的规则
ARM-Thumb 过程调用规范(ARM-Thumb Produce Call Standard,ATPCS)规定了一些子程序之间调用的基本规则,这些基本规则包括子程序调用过程中寄存器的使用规则、数据栈的使用规则、参数的传递规则。这也使得单独编译的C语言程序和汇编语言程序之间能够相互调用。
(4)C语言调用汇编语言
在汇编程序中使用 EXPORT伪指令作声明,使得程序可以被别的程序调用。在C语言程序中使用EXTERN关键词声明该汇编程序。
(5)汇编语言程序调用C语言程序
在C语言程序中,不需要使用任何关键字来声明将被汇编语言调用的C语言程序,但是在汇编语言程序调用C语言程序之前,需要在汇编语言程序中使用IMPORT伪操作来声明该C语言程序。在汇编语言程序中通过BL指令来调用子程序。
(6)C语言程序嵌入汇编语言程序的方法
armcc和armcpp支持完整的ARM指令集,tcc和tcpp支持Thumb指令集。
①内嵌汇编的语法格式
ASM
汇编指令序列;
其中 ASM 可大写也可小写,前面的“_ _”为两个下画线“_”
②内嵌汇编的主要特点
a.内嵌的操作数只能是无符号数,但可以是寄存器、常量或C语言表达式。
b.内嵌汇编使用物理寄存器有以下限制:
第一,不能直接向PC寄存器赋值,程序的跳转只能用B指令和BL指令实现。
第二,C语言编译时会用到寄存器 RO~R3、R12、RI3、R14,编程时尽量不要用这些物理寄存器,可使用R4~R7。编程时最好使用C语言的变量。如果编程时使用通用寄存器,则容易冲突。
c.嵌入汇编可以使用C语言的标号,但只能用B指令使用C语言中的标号,BL不能使用C语言中的标号
d.内嵌汇编不支持用于内存分配的伪指令,所有内存分配均由C语言完成。
e.内嵌汇编器与 armasm 汇编的区别:
第一,内嵌汇编不能通过寄存器PC返回当前指令的地址。
第二,内嵌汇编不支持ADR、ADRL以及LDR伪指令,而使用MOV Rn,expression 指令向寄存器赋值
第三,不支持标号表达式,不支持BX和BLX。
参考内容
文中内容均来自计算机等级考试《三级嵌入式系统开发》