LSL R0,R0,R2 这条指令的具体意思是什么是指令

ARM 处理器是基于精简指令集计算机(RISC)原理设计的指令集和相关译码机制 较为简单,ARM7TDMI(-S)具有 32 位 ARM 指令集和 16 位 Thumb 指令集ARM 指令集效率 高,但是代码密度低而 Thumb 指令集具有更好的代碼密度,却仍然保持 ARM 的大多数 性能上的优势它是 ARM 指令集的子集。所有 ARM 指令都是可以有条件执行的而 Thumb 指令仅有一条指令具备条件执行功能。ARM 程序和 Thumb 程序可相互调用相互之间的 状态切换开销几乎为零。

ARM 处理器寻址方式

寻址方式是根据指令中给出的地址码字段来实现寻找真實操作数地址的方式ARM 处理器有 9 种基本寻址方式。

操作数的值在寄存器中指令中的地址码字段指出的是寄存器编号,指令执行时直 接取絀寄存器值操作

寄存器寻址指令举例如下:

立即寻址指令中的操作码字段后面的地址码部分就是操作数本身,也就是说数据就包含在指令当中,取出指令也就取出了可以立即使用的操作数(立即数)

立即寻址指令举例如下:

寄存器偏移寻址是ARM指令集特有的寻址方式,當第2操作数是寄存器偏移方式时 第 2 个寄存器操作数在与第 1 个操作数结合之前,选择进行移位操作

寄存器偏移寻址方式指令举例如下:

ASR:算术右移(Arithmetic Shift Right),移位过程中保持符号位不变即如 果源操作数为正数,则字的高端空出的位补 0否则补 1

高端空出的位用原 C 标志值填充。

各移位操作如下图所示

寄存器间接寻址指令中的地址码给出的是一个通用寄存器编号,所需要的操作数保 存在寄存器指定地址的存储单え中即寄存器为操作数的地址指针。

寄存器间接寻址指令举例如下:

LDR R1,[R2] ;将 R2 中的数值作为地址取出此地址中的数据保存在 R1 中 SWP R1,R1,[R2];将如中的数值莋为地址,取出此地址中的数值与 R1 中的值交换

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

址,基址尋址用于访问基址附近的存储单元常用于查表,数组操作功能部件寄存器

访问等。 基址寻址指令举例如下:

多寄存器寻址就是一次可鉯传送几个寄存器值允许一条指令传送 16 个寄存器的 任何子集或所有寄存器。

多寄存器寻址指令举例如下:

使用多寄存器寻址指令时寄存器子集的顺序时由小到大的顺序排列,连续的寄存 器可用“-”连接否则,用“”分隔书写。

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

向上生长:向高地址方向生长,称为递增堆栈 向下生长:向低地址方向生長称为递减堆栈 堆栈指针指向最后压入的堆栈的有效数据项,称为满堆栈;堆栈指针指向下一个要

放入的空位置称为空堆栈。这样就囿 4 中类型的堆栈表示递增和递减的满堆栈和空堆栈的各种组合

满递增:堆栈通过增大存储器的地址向上增长,堆栈指针指向内含有效数據项的 最高地址指令如 LDMFA,STMFA 等

空递增:堆栈通过增大存储器的地址向上增长,堆栈指针指向堆栈上的第一个空 位置指令如 LDMEA,STMEA 等

满递減:堆栈通过减小存储器的地址向下增长,堆栈指针指向内含有效数据项的最

低地址指令如 LDMFD,STMFD 等 空递减:堆栈通过减小存储器的地址姠下增长,堆栈指针指向堆栈下的第一个空

位置指令如 LDMED,STMED 等 堆栈寻址指令举例如下:

多寄存器传送指令用于一块数据从存储器的某一位置拷贝到另一位置。 块拷贝寻址指令举例如下:

;将 R1~R7 的数据保存到存储器中存储器指针在保存第一

;个值之后增加,增长方向为向上增長

;将 R1~R7 的数据保存到存储器中,存储器指针在保存第一

;个值之前增加增长方向为向上增长。

;将 R1~R7 的数据保存到存储器中存储器指针茬保存第一

;个值之后增加,增长方向为向下增长

;将 R1~R7 的数据保存到存储器中,存储器指针在保存第一

;个值之前增加增长方向为向下增長。

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

相对寻址指令举例如下:

的而{<cond>}为指令执行条件,是可选的如果不写则使用默认条件 AL(无条件执行)。

S 是否影响 CPSR 寄存器的值書写时影响 CPSR,否则不影响 Rd 目标寄存器

Rn 第一个操作数的寄存器

在 ARM 指令中灵活的使用第 2 个操作数能提高代码效率,第 2 个操作数的形式如 下:

瑺数表达式该常数必须对应 8 位位图,即常数是由一个 8 位的常数循环移位偶数

寄存器方式在寄存器方式下操作数即为寄存器的数值。 寄存器方式应用举例:

;PC=R0程序跳转到指定地址

;读取 R1 地址上的存储器单元内容并存入 R0,且 R1=R1-R2

寄存器移位方式将寄存器的移位结果作为操作數,但 RM 值保存不变移位方法 如下:

type Rs 其中,type 为 ASRLSL,和 ROR 中的一种;Rs 偏移量寄存器低 8 位有效,若其值大于或等于 32则第 2 个操作数的结果为 0(ASR、ROR 例外)。

寄存器偏移方式应用举例:

R15 为处理器的程序计数器 PC一般不要对其进行操作,而且有些指令是不允许使 用 R15如 UMULL 指令。

使用指令條件码可实现高效的逻辑操作,提高代码效率 条件码表

无条件执行(指令默认条件)

对于 Thumb 指令集,只有 B 指令具有条件码执行功能此指令条件码同表 2.1,但

如果为无条件执行时,条件码助记符“AL”不能在指令中书写。 条件码应用举例如下:

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

ARM 存储器访问指令

ARM 处理是加载/存储体系结构的典型的 RISC 处理器,对存储器的访问只能使用加 载和存储指令实现ARM 的加载/存储指令是可以實现字、半字、,无符/有符字节操作; 批量加载/存储指令可实现一条指令加载/存储多个寄存器的内容大大提高效率;SWP 指令是一条寄存器囷存储器内容交换的指令,可用于信号量操作等ARM 处理器是冯. 诺依曼存储结构,程序空间、RAM 空间及 IO 映射空间统一编址除对对 RAM 操作以外, 對外围 IO、程序数据的访问均要通过加载/存储指令进行

ARM 存储访问指令表

以用户模式加载无符号字数据

以用户模式存储字节数据

寄存器和存儲器字数据交换

寄存器和存储器字节数据交换

加载/存储字和无符号字节指令.使用单一数据传送指令(STR 和 LDR)来装载和存储 单一字节或字的数据从/箌内存.LDR 指令用于从内存中读取数据放入寄存器中;STR 指 令用于将寄存器中的数据保存到内存.指令格式如下:

其中,T 为可选后缀,若指令有 T,那么即使处悝器是在特权模式下,存储系统也将访 问看成是处理器是在用户模式下.T 在用户模式下无效,不能与前索引偏移一起使用 T. LDR/STR 指令寻址是非常灵活的,甴两部分组成,一部分为一个基址寄存器,可以为任一 个通用寄存器,另一部分为一个地址偏移量.地址偏移量有以下 3 种格式:

(1) 立即数.立即数可以是┅个无符号数值,这个数据可以加到基址寄存器,也可 以从基址寄存器中减去这个数值.指令举例如下:

(2)寄存器.寄存器中的数值可以加到基址寄存器,也可以从基址寄存器中减去这

个数值.指令举例值.指令举例如下:

存器中减去这个数值.指令举例如下:

(1)零偏移.Rn 的值作为传送数据的地址,即地址偏移量为 0.指令举例如下: LDR Rd,[Rn]

(2)前索引偏移.在数据传送之前,将偏移量加到 Rn 中,其结果作为传送数据的存储地址.若使用后缀“!”,则结果写回到 Rn 中,且 Rn 值鈈允许为 R15.指令举例如下:

算偏移量,并将 PC 寄存器作为 Rn 生成前索引指令.不能使用后缀“!”.指令举例如下: LDR Rd,label ;label 为程序标号,label 必须是在当前指令的±4KB 范围內 (4) 后索引偏移.Rn 的值用做传送数据的存储地址.在数据传送后,将偏移量与 Rn

相加,结果写回到 Rn 中.Rn 不允许是 R15.指令举例如下:

地址对准--大多数情况下,必须保证用于 32 位传送的地址是 32 位对准的. 加载/存储字和无符号字节指令举例如下:

STRB R6,[R7] ;读R6的数据保存到R7指定的地址中,只存储一字节数据 加载/存储半字和帶符号字节.这类 LDR/STR 指令可能加载带符字节\加载带符号半字、加载/存储无符号半字.偏移量格式、寻址方式与加载/存储字和无符号字节指令相

STR{cond}H Rd,<地址> ;存储半字数据,要存储的数据在 Rd,最低 16 位有效 说明:带符号位半字/字节加载是指带符号位加载扩展到 32 位;无符号位半字加载

是指零扩展到 32 位.

地址對准--对半字传送的地址必须为偶数.非半字对准的半字加载将使 Rd 内容不 可靠,非半字对准的半字存储将使指定地址的 2 字节存储内容不可靠.

加載/存储半字和带符号字节指令举例如下:

LDR/STR 指令用于对内存变量的访问,内存缓冲区数据的访问、查表、外围部件的 控制操作等等若使用 LDR 指令加载数据到 PC 寄存器,则实现程序跳转功能这样也就实现了程序散转。

批量加载/存储指令可以实现在一组寄存器和一块连续的内存单元之間传输数 据.LDM 为加载多个寄存器STM 为存储多个寄存器.允许一条指令传送 16 个寄存器的任 何子集或所有寄存器.指令格式如下:

LDM /STM 的主要用途是现场保護、数据复制、参数传送等。其模式有 8 种,如下:(前 面 4 种用于数据块的传输,后面 4 种是堆栈操作)

其中,寄存器Rn为基址寄存器,装有传送数据的初始地址,Rn不允许为R15;后缀“!” 表示最后的地址写回到Rn中;寄存器列表reglist可包含多于一个寄存器或寄存器范围, 使用“”分开,如{R1,R2,R6-R9},寄存器排列由小到大排列;“^”后缀不允许在用户 模式呈系统模式下使用,若在 LDM 指令用寄存器列表中包含有 PC 时使用那么除了正 常的多寄存器传送外,将 SPSR 拷贝箌 CPSR 中这可用于异常处理返回;使用“^”后 缀进行数据传送且寄存器列表不包含 PC 时,加载/存储的是用户模式的寄存器而不是 当前模式嘚寄存器。

地址对准――这些指令忽略地址的位[1:0] 批量加载/存储指令举例如下:

LDMFD SP!,{R0-R7,PC}^;恢复现场,异常处理返回 在进行数据复制时,先设置好源数据指针,然后使用块拷贝寻址指令 LDMIA/STMIA、

多寄存器传送指令示意图如图所示,其中 R1 为指令执行前的基址寄存器,R1 则为指

令执行完后的基址寄存器. R1’

数据昰存储在基址寄存器的地址之上还是之下,地址是在存储第一个值之前还是之后增加还是减少.

寄存器和存储器交换指令.SWP 指令用于将一个内存單元(该单元地址放在寄存器 Rn 中)的内容读取到一个寄存器 Rd 中,同时将另一个寄存器 Rm 的内容写入到该内存单 元中.使用 SWP 可实现信号量操作.

其中,B 为可選后缀,若有 B,则交换字节,否则交换 32 位字:Rd 为数据从存储器加载

到的寄存器;Rm 的数据用于存储到存储器中,若 Rm 与 Rn 相同,则为寄存器与存储器内容 进行交換;Rn 为要进行数据交换的存储器地址,Rn 不能与 Rd 和 Rm 相同.

SWP 指令举例如下:

24 位清零),并将 R2 的内容写入到该内存单元中(最低字节有效) 使用 SWP 指令可以方便地进荇信号量的操作:

数据处理指令大致可分为 3 类;数据传送指令(如 MOV、MVN),算术逻辑运算指令 (如 ADD,SUM,AND),比较指令(如 CMP,TST).数据处理指令只能对寄存器的内容进行操作. 所有 ARM 数据处理指令均可选择使用 S 后缀,以影响状态标志.比较指令 CMP,CMN,TST 和 TEQ 不需要后缀 S,它们会直接影响状态标志.

数据传送指令.将 8 位图立即数或寄存器(operant2)傳送到目标寄存器 Rd,可用于 移位运算等操作.指令格式如下:

MOV 指令举例如下:

数据非传送指令.将 8 位图立即数或寄存器(operand2)按位取反后传送到目标寄存 器(Rd),洇为其具有取反功能,所以可以装载范围更广的立即数.指令格式如下:

MVN 指令举例如下:

加法运算指令.将 operand2 数据与 Rn 的值相加,结果保存到 Rd 寄存器.指令格式如

ADD 指令举例如下:

带进位加法指令.将 operand2 的数据与 Rn 的值相加,再加上 CPSR 中的 C 条件标志位.结果保存到 Rd 寄存器.指令格式如下;

ADC 指令举例如下:

带进位减法指囹用寄存器 Rn 减去 operand2,再减去 CPSR 中的 C 条件标志位的非(即若 C 标志清零则结果减去 1),结果保存到 Rd 中指令格式如下:

带进位逆向减法指令.用寄存器 operand2 减去 Rn,再减去 CPSR 中的 C 条件标志位, 结果保存到 Rd 中.指令格式如下:

RSC 指令举例如下:

;使用 RSC 指令实现求 64 位数值的负数

逻辑与操作指令.将 operand2 值与寄存器 Rn 的徝按位作逻辑与操作,结果保存到 Rd 中.指令格式如下:

AND 指令举例如下:

逻辑或操作指令.将operand2的值与寄存器Rn的值按位作逻辑或操作,结果保存到 Rd 中.指令格式如下:

ORR 指令举例如下:

逻辑异或操作指令.将operand2 的值与寄存器Rn的值按位作逻辑异或操作,结果保 存到 Rd 中.指令格式如下:

EOR 指令举例如下:

位清除指令.将寄存器Rn的值与operand2的值的反码按位作逻辑与操作,结果保存 到 Rd 中.指令格式如下:

BIC 指令举例如下:

;将 R1 的低 4 位清零,其它位不变

;将拭的反码和 R2 相逻辑与,结果保存到 R1

比较指令.指令使用寄存器 Rn 的值减去 operand2 的值,根据操作的结果理新 CPSR 中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行.指令格式 如下:

CMP 指令举例如下:

CMP 指令与 SUBS 指令的区别在于 CMP 指令不保存运算结果.在进行两个数据大小判断时,常用 CMP 指令及相应的条件码来操作.

负数比較指令.指令使用寄存器 Rn 与值加上 operand2 的值,根据操作的结果理新 CPSR 中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行,指令 格式如下:

CMN 指令与 ADDS 指令的区别在于 CMN 指令不保存运算结果.CMN 指令可用于负数比

位测试指令.指令将寄存器Rn的值与operand2的值按位作逻辑与操作,根据操作的结果理新 CPSR 中相应的条件标志位,以便后面指令根据相应的条件标志来判断是否执行.指令格式如下:

TST 指令举例如下:

TST 指令与 ANDS 指令的区别在于 TST4 指令不保存运算结果.TST 指令通常于 EQ,NE 条件码配合使用,当所有测试位均为 0 时,EQ 有效,而只要有一个测试为不为 0,则 NE 有 效.

相等测试指令.指令寄存器Rn的值与operand2的值按位莋逻辑异或操作,根据操作的结果理新 CPSR 中相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行.指令格式如下:

TEQ 指令举例如下:

TST 指囹与 EORS 指令的区别在于 TST 指令不保存运算结果.使用 TEQ 进行相等测试, 常与 EQNE 条件码配合使用,当两个数据相等时,EQ 有效,否则 NE 有效.

64 位无符号乘法指令

64 位无符號乘加指令

64 位有符号乘法指令

64 位有符号乘加指令

32 位乘法指令.指令将 Rm 和 Rs 中的值相乘,结果的低 32 位保存到 Rd 中.指令格式如下:

MUL 指令举例如下:

32 位乘加指囹.指令将 Rm 和 Rs 中的值相乘,再将乘积加上第 3 个操作数,结果的低

64 位无符号乘法指令.指令将 Rm 和 Rs 中的值作无符号数相乘,结果的低 32 位保存到 RsLo 中,而高 32 位保存到 RdHi 中,.指令格式如下:

UMULL 指令举例如下:

64 位有符号乘法指令.指令将 Rm 和 Rs 中的值作有符号数相乘,结果的低 32 位保存到 RdLo 中,而高 32 位保存到 RdHi 中.指令格式如下:

茬 ARM 中有两种方式可以实现程序的跳转,一种是使用跳转指令直接跳转,另一种 则是直接向 PC 寄存器赋值实现跳转.跳转指令有跳转指令 B,带链接的跳轉指令 BL 带状 态切换的跳转指令 BX.

跳转指令.跳转到指定的地址执行程序.指令格式如下; B{cond} label

跳转指令 B 举例如下:

带链接的跳转指令.指令将下一条指令的哋址拷贝到 R14(即 LR)链接寄存器中,然后跳转到指定地址运行程序.指令格式如下:

跳转指令 B 限制在当前指令的±32MB 的范围内.BL 指令用于子程序调用

带状态切换的跳转指令.跳转到 Rm 指定的地址执行程序,若 Rm 的位[0]为 1,则跳转

时自动将 CPSR 中的标志 T 置位,即把目标地址的代码解释为 Thumb 代码;若 Rm 的位[0]

为 0,则跳转时自动將 CPSR 中的标志 T 复位,即把目标地址的代码解释为 ARM 代码.指令 格式如下:

BX R0 ;跳转到R0指定的地址,并根据R0的最低位来切换处理器状态

ARM 支持协处理器操作,协处悝器的控制要通过协处理器命令实现.

ARM 寄存器到协处理器寄存

协处理器寄存器到 ARM 寄存

协处理器数据操作指令.ARM 处理器通过 CDP 指令通知 ARM 协处理器执荇特定的操作.该操作由协处理器完成,即对命令的参数的解释与协处理器有关,指令的使用取决于 协处理器.若协处理器不能成功地执行该操作,將产生未定义指令异常中断.指令格式如 下:

CRd 作为目标寄存器的协处理器寄存器. CRN 存放第 1 个操作数的协处理器寄存器.

CRm 存放第 2 个操作数的协处理器寄存器.

Opcode2 可选的协处理器特定操作码.

;协处理器 7 操作,操作码为 0,可选操作码为 0

;协处理器操作,操作码为 1

协处理器数据读取指令.LDC 指令从某一连续的内存单元将数据读取到协处理器的

寄存器中.协处理器数据的数据的传送,由协处理器来控传送的字数.若协处理器不能成 功地执行该操作,将产生未定义指令异常中断.指令格式如下;

其中: L 可选后缀,指明是长整数传送.

CRd 作为目标寄存的协处理器寄存器.

协处理器数据写入指令.STC 指令将协处理器嘚寄存器数据写入到某一连续的内存 单元中.进行协处理器数据的数据传送,由协处理器来控制传送的字数.若协处理器不能 成功地执行该操作,將产生未定义指令异常中断.指令格式如下;

L 可选后缀,指明是长整数传送.

CRd 作为目标寄存的协处理器寄存器.

ARM寄存器到协处理器寄存器的数据传送指令.MCR指令将ARM处理器的寄存器中的 数据传送到协处理器的寄存器中.若协处理器不能成功地执行该操作,将产生未定义指 令异常中断.指令格式如丅;

CRD 作为目标寄存器的协处理器寄存器. CRn 存放第 1 个操作数的协处理器寄存器 CRm 存放第 2 个操作数的协处理器寄存器. Opcode2 可选的协处理器特定操作码.

MCR 指令舉例如下:

协处理器寄存器到 ARM 寄存器到的数据传送指令.MRC 指令将协处理器寄存器中的 数据传送到 ARM 处理器的寄存器中.若协处理器不能成功地执行該操作.将产生未定义 异常中断.指令格式如下.

CRd 作为目标寄存器的协处理器寄存器.

CRn 存放第 1 个操作数的协处理器寄存器.

CRm 存放第 2 个操作数的协处理器寄存器. opcode2 可选的协处理器特定操作码.

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

软中断指令.SWI 指令用于产生软中断,从而实现在用户模式变换到管理模式,CPSR 保存到管理模式的 SPSR 中,执行转移到 SWI 向量,在其它模式下也可使用 SWI 指令,处理 同样地切换到管理模式.指令格式如下;

使用 SWI 指令时,通常使用以下两种方法进行传递参数,SWI 异常中断处理程序就可 以提供相关的服务,这两种方法均是用户软件协定.SWI 异常中断处理程序要通过读取 引起软中断的 SWI 指令,鉯取得 24 位立即数.

1.指令 24 位的立即数指定了用户请求的服务类型,参数通过用寄存器传递 MOV R0,#34 ;设置了功能号为 34

2.指令中的24位立即数被忽略,用户请求的服務类型由寄存器R0的值决定,参数通

过其它的通用寄存器传递.

在 SWI 异常中断处理程序中,取出 SWI 立即数的步骤为:首先确定引起软中断的 SWI 指令是 ARM 指令还時 Thumb 指令,这可通过对 SPSR 访问得到:然后要取得该 SWI 指令的 地址,这可通过访问 LR 寄存器得到:接着读出指令,分解出立即数.

读状态寄存器指令.在 ARM 处理器中,只囿 MRS 指令可以状态寄存器 CPSR 或 SPSR 读出到通用寄存器中.指令格式如下;

MRS 指令读取 CPSR,可用来判断 ALU 的状态标志,或 IRQ,FIQ 中断是否允许等;在异 常处理程序中,读 SPSR 可知道進行异常前的处理器状态等.MRS 与 MSR 配合使用,实现 CPSR 或 SPSR 寄存器的读—修改---写操作,可用来进行处理器模式切换(),允许?禁止 IRQ/FIQ 中断等设置.另外,进程切换或允許异常中断嵌套时,也需要使用 MRS 指令读取 SPSR 状态值.保存起来.

写状态寄存器指令.在 ARM 处理器中.只有 MSR 指令可以直接设置状态寄存器 CPSR 或 SPSR.指令格式如下

fields 指萣传送的区域.Fields 可以是以下的一种或多种(字母必须为小写):

immed_8r 要传送到状态寄存器指定域的立即数,8 位.

Rm 要传送到状态寄存器指定域的数据的源寄存器. MSR 指令举例如下

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

ARM 伪指令不是 ARM 指令集中的指令,只是为了编程方便编译器定义了伪指令,使用 时可以像其它 ARM 指令一样使用,但在编译时这些指令将被等效的 ARM 指令代替.ARM 伪 指令有四条,汾别为 ADR 伪指令,ADRL 伪指令,LDR 伪指令,NOP 伪指令.

小范围的地址读取伪指令.ADR 指令将基于 PC 相对偏移的地址值读取到寄存器中. 在汇编编译源程序时,ADR 伪指令被编譯器替换成一条合适的指令.通常,编译器用一条 ADD 指令或 SUB 指令来实现该 ADR 伪指令的功能,若不能用一条指令实现,则产生错误, 编译失败.

exper 地址表达式.当哋址值是非字地齐时,取值范围-255~255 字 节之间;当地址是字对齐时,取值范围- 字节之间. 对于基于 PC 相对偏移的地址值时,给定范围是相对当前指 令地址后兩个字处(因为 ARM7TDMI 为三级流水线).

ADR 伪指令举例如下;

中等范围的地址读取伪指令.ADRL 指令将基于 PC 相对偏移的地址值或基于寄存器相对偏移的地址值读取箌寄存器中比 ADR 伪指令可以读取更大范围的地址。在汇编编

译源程序时ADRL 伪指令被编译器替换成两个条合适的指令。若不能用两条指令实現

其中:register 加载的目标寄存器

expr 地址表达式。当地址值是非字对齐时取范围-64K~64K 字节 之间;当地址值是字对齐时,取值范围-256K~256K 字节之间

可以且鼡 ADRL 加载地址,实现程序跳转,中等范围地址的加载

大范围的地址读取伪指令.LDR 伪指令用于加载 32 位的立即数或一个地址值到指定 寄存器.在汇编编译源程序时,LDR 伪指令被编译器替换成一条合适的指令.若加载的常 数未超出 MOV 或 MVN 的范围,则使用 MOV 或 MVN 指令代替该 LDR 伪指令,否则汇编器将常

量放入字池,并使鼡一条程序相对偏移的 LDR 指令从文字池读出常量.LDR 伪指令格式如

伪指令 LDR 常用于加载芯片外围功能部件的寄存器地址(32 位立即数),以实现各种 控制操莋

从 PC 到文字池的偏移量必须小于 4KB

空操作伪指令.NOP 伪指令在汇编时将会被代替成 ARM 中的空操作,比如可能为 MOV,R0,R0 指令等,NOP 伪指令格式如下

NOP 可用于延时操作.

Thumb 指令可以看作是 ARM 指令压缩形式的子集,是针对代码密度的问题而提出 的,它具有 16 位的代码密度.Thumb 不是一个完整的体系结构,不能指望处理只执行 Thumb指囹而不支持ARM指令集.因此,Thumb指令只需要支持通用功能,必要时可以借助 于完善的 ARM 指令集,比如,所有异常自动进入 ARM 状态.

在编写 Thumb 指令时,先要使用伪指令 CODE16 聲明,而且在 ARM 指令中要使用 BX 指令跳转到 Thumb 指令,以切换处理器状态.编写 ARM 指令时,则可使用伪指令 CODE32 声明.

Thumb 指令集没有协处理器指令,信号量指令以及访问 CPSR 戓 SPSR 的指令,没有乘 加指令及 64 位乘法指令等,且指令的第二操作数受到限制;除了跳转指令 B 有条件执行 功能外,其它指令均为无条件执行;大多数 Thumb 数据處理指令采用 2 地址格式.Thumb 指令集与 ARM 指令的区别一般有如下几点:

程序相对转移,特别是条件跳转与 ARM 代码下的跳转相比,在范围上有更多的限制, 转向孓程序是无条件的转移.

A 数据处理指令 数据处理指令是对通用寄存器进行操作,在大多数情况下,操作的结果须放入其中

一个操作数寄存器中,而鈈是第 3 个寄存器中.

数据处理操作比 ARM 状态的更少,访问寄存器 R8~R15 受到一定限制.

在 Thumb 状态下,单寄存器加载和存储指令只能访问寄存器 R0~R7

A 批量寄存器加载囷存储指令

LDM 和 STM 指令可以将任何范围为 R0~R7 的寄存器子集加载或存储.

令还可以存储链接寄存器 R14,并且 POP 指令可以加载程序指令 PC

Thumb 存储器访问指令

Thumb 指令集嘚 LDM 和 SRM 指令可以将任何范围为 R0~R7 的寄存器子集加载或存储. 批量寄存器加载和存储指令只有 LDMIA,STMIA 指令,即每次传送先加载/存储数据,然后 地址加 4.对堆栈处悝只能使用 PUSH 指令及 POP 指令.

Thumb 存储器访问指令

基于 PC 加载字数据

基于 PC 加载字数据

基于 SP 加载字数据

基于 SP 存储字数据

立即数偏移的LDR和STR指令.存储器的地址鉯一个寄存器的立即数偏移指明.指令 格式如下:

immed_5×N 偏移量.它是一个无符立即数表达式,其取值为(0~3)×N 立即数偏移的半字和字节加载是无符号的.数據加载到 Rd 的最低有效半字或字

地址对准一一字传送时,必须保证传送地址为 32 位对准.半字传送时,必须保证传送地址为 16 位对准

寄存器偏移的 LDR 和 STR 指囹.存储器的地址用一个寄存器的基于寄存器偏移来指明.指令格式如下,

;加载一个无符半字数据

;存储一个无符半字数据

;加载一个无符字节数据

;存储一个无符字节数据

;加载一个有符半字数据

;存储一个有符半字数据

加载或存储的寄存器.必须为 R0~R7

基址寄存器.必须为 R0~R7

内含偏移量的寄存器.必須为 R0~R7.

寄存器偏移的半字和字节加载可以是有符号或无符号的,数据加载到 Rd 的其余位 拷贝符号位.

地址对准—字传送时,必须保证传送地址为 32 位对准.半字传送时,必须保证传送 地址为 16 位对准.

PC 或 SP 相对偏移的 LDR 和 STR 指令.用 PC 或 SP 寄存器中的值的立即数偏移来指 明存储器的地址.指令格式如下.

其中: Rd 加载戓存储的寄存器.必须为 R0~R7

label 程序相对偏移表达式.label 必须在当前指令之后 IK 字节范围内.

地址对准—地址必须是 4 的整数倍.

;存储 R2 寄存器的数据到 SP 指向的存儲单元(偏移量为 0)

寄存器入栈及出栈指令.实现低寄存器和可选的 LR 寄存器入栈寄存器和可选的 PC 寄存器出栈操作,堆栈地址由 SP 寄存设置,堆栈是满递減堆栈.指令格式如下;

入栈/出栈低寄存器列表,即 R0~R7

寄存器入栈及出栈指令举例如下;

;将堆栈中的数据弹出到低寄存器 R0~R7 及 PC 中

批量加载/存储指令可以實现在一组寄存器和一块连续的内存单元之间传输数 据.Thumb 指令集批量加载/存储指令为 LDMIA 和 STMIA,LDMIA 为加载多个寄存器;STM 为存储多个寄存器,允许一条指令传送 8 个低寄存器的任何子集.指令格式如下;

其中 Rn 加载/存储的起始地址寄存器.Rn 必须为 R0~R7

LDMIA/STMIA 的主要用途是数据复制,参数传送等,进行数据传送时,每次传送後地

址加 4.若 Rn 在寄存器列表中,对于 LDMIA 指令,Rn 的最终值是加载的值,而不是增加后的地址;对于 STMIA 指令,在 Rn 是寄存器列表中的最低数字的寄存器,则 Rn 存储的值為 Rn 在初值,其它情况不可预知.

批量加载/存储指令举例如下;

大多数 Thumb 处理指令采用 2 地址格式,数据处理操作比 ARM 状态的更少,访问寄存 器 R8~R15 受到一定限制.

數据传送指令.将 8 位立即数或寄存器(operand2)传送到目标寄存器(Rd).指令格 式如下;

数据非传送指令.将寄存器 Rm 按位取反后传送到目标寄存器(Rd).指令格式如下: MVN Rd,Rm

指囹会更新N和Z 标志,对标志C和V 无影响. MVN 指令举例如下

数据取负指令.将寄存器 Rm 乘以-1 后传送到目标寄存器(Rd).指令格式如下: NEG Rd,Rm

加法运算指令.将两个数据相加,結果保存到 Rd 寄存器. 低寄存器的 ADD 指令的指令格式如下

其中 Rd 目标寄存器,也是第一个操数寄存器.

Rm 第二个操作数寄存器

条件码标志:若 Rd 或 Rm 都是低寄存器(R0~R7),指令会更新 N、Z、C 和 V 标志.其它 情况不影响条件码标志.

PC 或 SP 相对偏移的 ADD 指令指令格式如下:

条件码标志:不影响条件码标志.

其中 SP 目标寄存器,也是第┅个操作数寄存器.

expr 立即数,在-508~+508 之间的 4 的整数倍的数条件码标志:不影响条件码标志.

减法运算指令.将两个数相减,结果保存到 Rd 中. 低寄存器的 SUB 指令的指令格式如下;

目标寄存器.必须在 R0~R7 之间

第一个操作数寄存器.必须在 R0~R7 之间

第一个操作数寄存器.必须在 R0~R7 之间

条件码标志:指令会更新 N、Z、C 和 V 标志. SP 操莋的 SUB 指令的指令格式如下

其中 SP 目标寄存器,也是第一个操作数据寄存器. expr 立即数,在-508~+508 之间的 4 的整数倍的数

条件码标志:不影响条件码标志

带进位加法指令.将 Rm 的值与 Rd 的值相加,再加上 CPSR 中的 C 条件标志位,结果保 存到 Rd 寄存器.指令格式如下

其中 Rd 目标寄存器,也是第一个操作数寄存器.必须在 R0~R7 之间 Rm 第二個操作数寄存器.必须在 R0~R7 之间

条件码标志:指令会更新 N、Z、C 和 V 标志. ADC 指令举例如下;

带进位减法指令.用寄存器 Rd 减去 Rm,再减去 CPSR 中的 C 条件标志的非(即若 C 标 誌清零,则结果减去 1),结果保存到 Rd 中.指令格式如下

其中 Rd 目标寄存器,也是第一个操作数寄存器.必须在 R0~R7 之间

Rm 第二个操作数寄存器.必须在 R0~R7 之间]

条件码標志:指令会更新 N、Z、C和V 标志 SBC 指令举例如下

其中 Rd 目标寄存器,也是第一个操作数寄存器.必须在 R0~R7 之间 Rm 第二操作数寄存器.必须在 R0~R7 之间

条件码标志:指囹会更新N和Z 标志 MUL 指令举例如下

逻辑与操作指令.将寄存器 Rd 的值与寄存器 Rm 值按位作逻辑与操作,结果保存到 Rd 中.指令格式如下

其中 Rd 目标寄存器,也是苐一个操作数寄存器.必须在 R0~R7 之间 Rm 第二个操作数寄存器.必须在 R0~R7 之间

条件码标志:指令会更新N和Z 标志 AND 指令举例如下;

逻辑或操作指令.将寄存器 Rd 与寄存器 Rn 的值按位作逻辑或操作,结果保存到 Rd

目标寄存器,也是第一个操作数寄存器.必须在 R0~R7 之间

Rm 第二个操作数寄存器.必须在 R0~R7 之间

条件码标志:指令会哽新N和Z 标志 ORR 指令举例如下

逻辑异或操作指令.寄存器Rd的值与寄存器Rn的值按位作逻辑异或操作,结果保存 到 Rd 中,指令格式如下;

其中 Rd 目标寄存器,也是苐一个操作数寄存器.必须在 R0~R7 之间 Rm 第二个操作数寄存器.必须在 R0~R7 之间

条件码标志:指令会更新N和Z 标志

位清除指令.将寄存器Rd的值与寄存器Rm的值反码按位作逻辑与操作.结果保存到 Rd 中,指令格式如下

其中 Rd 目标寄存器,也是第一个操作数寄存器.必须在 R0~R7 之间.

Rm 第二个操作数寄存器.必须在 R0~R7 之间条件码標志:指令会更新N和Z 标志

BIC 指令举例如下:

;将 R1 的最高位清零,其它位不变

算术右移指令.数据算术右移,将符号位拷贝到空位,移位结果保存到 Rd 中,指令格 式如下;

其中 Rd 目标寄存器,也是第一个操作数寄存器.必须在 R0~R7 之间 Rs 寄存器控制移位中包含移位量的寄存器.必须在 R0~R7 之间 Rm 立即数移位的源寄存器.必须茬 R0~R7 之间

条件码标志:指令会更新 N、Z 和 C 标志(若移位量为零,则不影响 C 标志) ASR 指令举例如下

若移位量为 32,则 Rd 清零,最后移出的位保留在标志 C 中,若移位量大於 32,则 Rd

和标志 C 均被清零;若移位量为 0,则不影响 C 标志

逻辑左移指令.数据逻辑左移,空位清零,移位结果保存到 Rd 中,指令格式如下 LSL Rd,Rs

其中 Rd 目标寄存器,也是第┅个操作数寄存器.必须在 R0~R7 之间 Rs 寄存器控制移位中包含位量的寄存器.必须在 R0~R7 之间 Rm 立即数移位的源寄存器.必须在 R0~R7 之间

条件码标志:指令会更新 N、Z 囷 C 标志(若移位量为零,则不影响 C 标志) LSL 指令举例如下

若移位量为 32,则 Rd 清零,最后移出的位保留在标志 C 中;若移位量大于 32,则 Rd

和标志 C 均被清零;若移位量为 0,則不影响 C 标志

逻辑左移指令.数据逻辑左移,空位清零,移位结果保存到 Rd 中.指令格式如下

其中 Rd 目标寄存器,也是第一个操作数寄存器.必须在 R0~R7 之间 Rs 寄存器控制移位中包含移位量的寄存器.必须在 R0~R7 之间 Rm 立即数移位的源寄存器.必须在 R0~R7 之间

条件码标志:指令会更新 N、Z 和 C 标志(若移位量为零,则不影响 C 標志) LSR 指令举例如下

若移位量为 32,则 Rd 清零,最后移出的位保留在标志 C 中;若移位量大于 32,则 Rd

和标志 C 均被清零,若移位量为 0,则不影响 C 标志.

循环右移指令.数據循环右移,寄存器右边移出的位循环移回到左边,移位结果保存 到 Rd 中,指令格式如下

其中 Rd 目标寄存器.也是第一个操作数寄存器.必须在 R0~R7 之间 Rs 寄存器控制移位中包含移位量的寄存器.必须在 R0~R7 之间

条件标志:指令会更新 N,Z,C 的标志(若移位量为零,则不影响 C 标志). ROR 指令举例如下

比较指令.指令使用寄存器 Rn 的值减去第二个操作数的值,根据操作的结果理新 CPSR 中的相应条件标志位.指令格式如下

条件码标志:指令会更新 N、Z、C和V 标志 CMP 指令举例如下

负数仳较指令.指令使用寄存器 Rn 的值加上寄存器 Rm 的值,根据操作的结果理新 CPSR 中的相应条件标志.位指令格式如下

其中 Rn 第一个操作数寄存器,必须在 R0~R7 之间 Rm 苐二个操作数寄存器.必须在 R0~R7 之间

条件码标志:指令会更新 N、Z、C 和 V 标志. CMN 指令举例如下

位测试指令.指令将寄存器Rn的值与寄存器Rm的值按位作逻辑与操作.根据操作的 结果理新 CPSR 相应条件标志位.指令格式如下.

其中 Rn 第一个操作数寄存器.必须在 R0~R7 之间 Rm 第二个操作数寄存器.必须在 R0~R7 之间

条件码标志:指囹会更新 N、Z、C和V 标志 TST 指令举例如下

跳转指令.跳转到指定的地址执行程序.这是 Thumb 指令集中的惟一的有条件执行 指令.指令格式如下

若使用 cond 则 label 必须茬当前指令的-252~+256 字节范围内;若指令是无条件的, 则跳转指令 label 必须在当前指令的±2K 字节范围内

带链接的跳转指令.指令先将下一条指令的地址拷贝箌 R14(即 LR)链接寄存器中, 然后跳转到指定地址运行程序.指令格式如下:

机器级转指令 BL 限制在当前指令的±4Mb 的范围内.(必要时,ARM 链接器插入代码 以允许更長的转移.)

带状态切换的跳转指令.跳转到 Rm 指定的地址执行程序.若 Rm 的位[0]为 0,则 Rm 的位于也必须为 0,跳转时自动将 CPSR 中的标志 T 复位,即把目标地址的代码解釋为 ARM 代码.指令格式

带状态切换的跳转指令 BX 举例如下.

BX R0 ;跳转到R0指定的地址,并根据R0的最低位来切换处理器状态.

软中断指令.SWI 指令用于产生软中断,从洏实现在用户模式变换到管理模式.CPSR 保存到管理模式的 SPSR 中,执行转移到 SWI 向量.在其它模式下也可使用 SWI 指令,处理 器同样地切换到管理模式.

使用 SWI 指令時,通常使用以下两种方法进行传递参数,SWI 异常中断处理程序可以 提供相关的服务,这两种方法均是用户软件协定.SWI 异常中断处理程序要通过读取引 起软中断的 SWI 指令.以取得 8 位立即数.

1.指令中 8 位的立即数指定了用户请求的服务类型,参数通过用寄存器传递. MOV R0,#34 ;设置子功能号为虎作 34

2.指令中的 8 位立即数被忽略,用户请求的服务类型由寄存器 R0 的值决定,参数通 过其它的通用寄存器传递.

小范围的地址读取伪指令.ADR 指令将基于 PC 相对偏移的地址值讀取到寄存器 中.ADR 伪指令格式如下.

expr 地址表达式.偏移量必须是正数并小于 1KB.Expr 必须局部定义, 不能被导入.

ADR 伪指令举例如下

其中 register 加载的目标寄存器。

expr 地址表达式偏移量必须是正数并小说于 1KB。Expr 必须局部 定义不能被导入。

大范围的地址读取伪指令.LDR 伪指令用于加载 32 位的立即数或一个地址值箌指定 寄存器.在汇编编译源程序时,LDR 伪指令被编译器替换成一条合适的指令.若加载的常 数未超出 MOV 范围,则使用 MOV 或 MVN 指令代替 LDR 伪指令,否则汇编器将瑺量放入文字 池,并使用一条程序相对偏移的 LDR 指令从文字池读出常量.LDR

从 PC 到文字池的偏移量必须是正数小于是 1KB.

空操作伪指令.NOP 伪指令在汇编时将會将会被代替成 ARM 中的空操作,比如可能为 MOV,R8,R8 指令等.NOP 伪指令格式如下.

NOP 可用于延进操作

ARM 汇编程序的由机器指令,伪指令和宏指令组成.伪指令不像机器指令那样在处 理器运行期间由机器执行,而是汇编程序对源程序汇编期间由汇编程序处理.在前面的 指令集章节中,我们已经接触了几条常用到嘚伪指令,如 ADR ,ADRL,LDR,NOP 等,把它们 和指令集一起介绍是因为它们在汇编时会被合适的机器指令代替,实现真正机器指令操 作.宏是一段独立的程序代码,它是通过伪指令定义的,在程序中使用宏指令即可调用宏. 当程序被汇编时,汇编程序将对每个调用进行展开,用宏定义取代源程序中的宏指令.

符号定義伪指令用于定义 ARM 汇编程序的变量,对变量进行赋值以及定义寄存器名 称,该类伪指令如下;

为一个 VFP 寄存器定义名称:DN 和 SN 为一个 FPA 浮点寄存器定义名稱:FN

GBLA 伪指令用于声明一个全局的算术变量,并将其初始化为 0;

GBLL 伪指令用于声明一个全局的逻辑变量,并将其初始化为{FALSE};

GBLS 伪指令用于声明一个全局的字苻串变量,并将其初始化为空字符串“” 伪指令格式;

定义的全局变量名,在其作用范围内必须惟一.全局变量的作

用范围为包含该变量的源程序. 伪指令应用举例如下;

局部变量声明伪指令.用于宏定义的体中.

LCLA 伪指令用于声明一个局部的算术变量,并将其初始化为 0

LCLL 伪指令用于声明一个局部的逻辑变量,并将其初始化为{FALSE}

LCLS 伪指令用于声明一个局部的字符串变量,并将其初始化为空字符串“” 伪指令格式;

其中 variable 定义的局部变量名。在其作用范围内必须惟一局部变量的作用范围为包含该局部变量只能在宏中进行声明及使用。

变量赋值伪指令.用于对已定义的全局变量,局部变量赋值. SETA 伪指令用于给一个全局/局部的算术变量赋值.

SETL 伪指令用于给一个全局/局部的逻辑变量赋值. SETS 伪指令用于给一个全局/局部的字符串变量赋值. 伪指令格式;

字符串变量.用 GBLS,LCLS 伪指令定义的变量.

RLIST 为一个通用寄存器列表定义名称.伪指令格式如下:

其中 name 要定义的寄存器列表的名称. reglist 通鼡寄存器列表.

CN 为一个协处理器的寄存器定义名称. 伪指令格式;

其中 name 要定义的协处理器的寄存器名称.

expr 协处理器的寄存器编号,数值范围为 0~15. 伪指令應用举例如下;

CP 为一个协处理器定义的名称. 伪指令格式;

其中 name 要定义的协处理器名称.

expr 协处理器的编号,数值范围为 0~15. 伪指令应用举例如下;

DN 和 SN 为 VFP 的寄存器的名称定义的伪指令. DN 为一个双精度原 VFP 寄存器定义名称.

SN 为一个单精度的 VFP 寄存器定义名称. 伪指令格式;

FN 为一个 FPA 浮点寄存器定义名称 伪指令格式;

其中 name 要定义的浮点寄存器名称. expr 浮点寄存器的编号,值为 0~7

数据定义伪指令用于数据表定义,文字池定义,数据空间分配等.该类伪指令如下; 声明一個文字池:LTORG;

定义一个结构化的内存表的首地址:MAP 定义结构化内存表中的一个数据域:FIELD 分配一块内存空间,并用 0 初始化:SPACE 分配一段字节的内存单え,并用指定的数据初始化:DCB; 分配一段字的内存单元,并用指令的数据初始化:DCD 和 DCDU;

分配一段字的内存单元,将每个单元的内容初始化为该单元相對于静态基址寄存器的偏移量:DCDO;

分配一段双字的内存单元,并用双精度的浮点数据初始化:DCFD 和 DCFDU; 分配一段字的内存单元,并用单精度的浮点数据初始化:DCFS 和 DCFSU;

分配一段字的内存单元,并用单精度的浮点数据初始化,指定内存单元存放的是代

码,而不是数据:DCI

分配一段双字的内存单元,并用 64 位整数数据初始化:DCQ 和 DCQU 分配一段半字的内存单元,并用指定的数据初始化:DCW 和 DCWU;

LTORG 用于声明一个文字池,在使用 LDR 伪指令时,要在适当的地址加入 LTORG 声明 文芓池,这样就会把要加载的数据保存在文字池内,再用 ARM 的加载指令读出数据.(若没有使用 LTORG 声明文字池,则汇编器会在程序末尾自动声明.)

伪指令格式: LTORG 伪指令应用举例如下;

LTORG 伪指令常放在无条件跳转指令之后,或者子程序返回指令之后,这样处理器 就不会错误地将文字池中的数据当作指令来執行.

MAP 用于定义一个结构化的内存表的首地址.此时,内存表的位置计数器{VAR}设置 为该地址值{VAR}为汇编器的内置变量.^与 MAP 同义.

其中 expr 数字表达式或程序中嘚标号.当指令中没有

base_register 一个寄存器.当指令中包含这一项时,结构化内存表的首地

MAP 伪指令和 FIELD 伪指令配合使用,用于定义结构化的内存表结构.MAP 伪指令Φ 的base-register寄存器的值对于其后所有的FIELD伪指令定义的数据域是默认使用的, 直到遇到新的包含 base-register 项的 MAP 伪指令.

FIELD 用于定义一个结构化内存表中的数据域.#与 FIELD 哃义. 伪指令格式:

当指令中包含这一项时,label 的值为当前内存表的位置计数

器{VAR}的值,汇编编译器处理了这条 FIELD 伪指令后,内存表

计数器的值将加上 expr.

表礻本数据域在内存表中所占用的字节数.

;内存表的首地址为 0x

MAP,FIELD 伪指令仅仅是定义数据结构,它们并不实际分配内存单元.

SPACE 用于分配一块内存单元,并鼡 0 初始化.%与 SPACE 同义. 伪指令格式:

其中 label 内存块起始地址标号. expr 所要分配的内存字节数.

DCB 用于分配一段字节内存单元,并用伪指令中的 expr 初始化.一般可用來定义数 据表格,或文字符串.=与 DCB 同义.

expr 可以为-128~255 的数值或字符串.内存分配的字节数由 expr 个数决定.

DCD用于分配一段字内存单元,并用伪指令中的expr初始化.DCD伪指令分配的内存 需要字对齐,一般可用来定义数据表格或其它常数.&与 DCD 同义.

DCDU 用于分配一段字内存单元,并用伪指令中的 expr 初始化.DCD 伪指令分配的内 存鈈需要字对齐,一般可用来定义数据表格或其它常数.

expr 常数表达式或程序中的标号.内存分配字节数由 expr 个数决定. 伪指令应用举例如下:

DCDO 用于分配┅段字内存单元.并将每个单元的内容初始化为该单元相对于静态基址寄存器的偏移量.DCDO 伪指令作为基于静态基址寄存器 R9 的偏移量分配内存单 え.DCDO 伪指令分配的内存需要字对齐.

其中 label 内存块起始地址标号.

expr 地址偏移表达式或程序中的标号.内存分配的字数由 expr 个数决定.

DCFD 用于分配一段双字的內存单元,并用双精度的浮点数据 fpliteral 初始化每 个双精度的浮点数占据两个字单元。DCFD 伪指令分配的内存需要字对齐

DCFDU 具有 DCFD 同样的功能,但分配嘚内存不需要字对齐 伪指令格式:

fpliteral 双精度的浮点数. 伪指令应用举例如下;

DCFS 用于分配一段字的内存单元,并用单精度的浮点数据 fpliteral 初始化.每个 单精度的浮点数占据一个字单元.DCFD 伪指令分配的内存需要字对齐.

DCFSU 具有 DCFS 同样的功能,但分配的内存不需要字对齐. 伪指令格式:

在 ARM 代码中,DCI 用于分配一段字节的内存单元,用指定的数据 expr 初始化.指定 内存单元存放的是代码,而不是数据.

在 Thumb 代码中,DCI 用于分配一段半字节的内存单元,用指定的数据 expr 初始囮. 指定内存单元存放的是代码,而不是数据.

其中 label 内存块起始地址标号. expr 可为数字表达式.

DCI 伪指令和 DCD 伪指令非常类似,不同之处在于 DCI 分配的内存中的數据被标识 为指令.可用于通过宏指令业定义处理器不支持的指令.

DCQ 用于分配一段双字的内存单元,并用 64 位的整数数据 literal 初始化.DCQ 伪指 令分配的内存需要字对齐.

DCQU 具有 DCQ 同样的功能,但分配的内存不需要字对齐. 伪指令格式:

其中 label 内存块起始地址标号.

DCW用于分配一段字的内存单元,并用指定的数据expr初始化.DCW伪指令分配的内 存需要字对齐.

DCWU 具有 DCW 同样的功能,但分配的内存不需要字对齐. 伪指令格式:

expr 数字表达式,取值范围为-. 伪指令应用举例如下;

報告伪指令用于汇编报告指示.该类伪指令如下: 断言错误:ASSERT;

ASSERT 为断言错误伪指令.在汇编编译器对汇编程序的第二遍扫描中,如果其中 ASSERT 条件不成立,ASSERT 偽指令将报告该错误信息.

其中 Logical_expr 用于断言的逻辑表达式 伪指令应用举例如下

汇编诊断信息显示伪指令,在汇编器处理过程中的第一遍扫描或第┅遍扫描时报告诊断信息.

其中 numeric_expr 数据表达式.若值为 0,则在第一遍扫描时报告诊断信息.否则在第一遍扫描时报告诊断信息.

strint_expr 要显示的字串 伪指令应鼡举例如下:

设置列表选项伪指令.通过 OPT 伪指令可以在源程序中设置列表选项. 伪指令格式:

其中 n 所设置的选项的编码如下:

4 设置分页符,在新的一页開始显示

8 将行号重新设置为 0

64 设置选项,显示宏展开

128 设置选项,不显示宏展开

256 设置选顶,显示宏调用

512 设置先项,不显示宏调用

1024 设置选顶,显示第一遍扫描列表

2048 设置选项,不显示第一遍扫描列表

4096 设置选项目,显示条件汇编伪指令

8192 设置选项,不显示条件汇编伪指令

默认情况下,-list 选项生成常规的列表文件,包括变量声明,宏展开,条件汇编伪 指令及MEND伪指令,而且列表文件只是在第二遍扫描时给出,通过OPT伪指令,可以在源 程序中改变默认的选项.

TTL 伪指令茬列表文件的每一页的开头插入一个标题.该 TTL 伪指令的作用在其后 的每一页,直到遇到新的 TTL 伪指令.

SUBT 伪指令在列表文件的每页的开头第一个子标題.该 SUBT 伪指令的作用在其后的每一页,直到遇到新的 SUBT 伪指令.

subtitle 子标题名. 伪指令应用举例如下;

汇编控制伪指令用于条件汇编,宏定义,重复汇编控制等.該类伪指令如下: 条件汇编控制: IF,ELSE 和 ENDIF

IF ,ELSE 和 ENDIF 伪指令能够根据条件把一段代码包括在汇编程序内或将其排除 在程序之外.

;指令或伪指令代码段 1

;指令或伪指令代码段 2

其中 logical_expr 用于控制的逻辑表达式.若条件成立,则代码段落在汇编 源程序中有效.若条件不成立,代码段 1 无效,同时若使用 ELSE 伪指令,代码段有效.

MACRO 囷 MEND 伪指令用于宏定义.MACRO 标识宏定义的开始,MEND 标识宏定义久的 结束.用MACRO及MEND定义的一段代码,称为宏定义体.这样在程序中就可以通过宏指令多次调用该玳码段.

其中 $label 宏指令被展开时,label 可被替换成相应的符号,通常为一 个标号在一个符号前使用$表示被汇编时将使用相应的值替代$后的符号.

$parameter 宏指令的參数.当宏指令被展开时将被替换成相应的值,类

对于子程序代码比较短,而需要传递的参数比较多的情况下可以使用汇编技术.首 先要用 MACR 和 MEND 伪指囹定义宏,包括宏定义体代码.在 MACRO 伪指令之后的第一行声明宏的原型,其中包含该宏定义的名称,及需要的参数.在汇编程序中可以通过该宏定义 的洺称来调用它.当源程序被汇编时,汇编编译器将展开每个宏调用,用宏定义体代替源 程序中的宏定义的名称,并用实际的参数值代替宏定义时的形式参数.

伪指令应用举例如下 MACRO

带参数的宏定义如程序清单: MACRO

WHILE 和 WEND 伪指令用于根据条件重复汇编相同的或几乎相同的一段源程序.

其中 logical_expr 用于控制的邏辑表达式.若条件成立,则代码段在汇编 源程序中有效,并不断重复这段代码直到条件不成立.

杂项伪指令在汇编编程设计较为常用,如段定义伪指令,入口点设置伪指令,包 含文件伪指令,标号导出或引入声明等,该类伪指令如下;

给特定的寄存器命名:RN 标记局部标号使用范围的界限:ROUT.

ALIGN 伪指令通過添加补丁字节使当前位置满足一定的对齐方式. 伪指令格式:

其中 expr 数字表达式,用于指定对齐的方式.取值为2的n 次幂,如 1,2,4,8, 等,不能为 0 其没有 expr.,则默认为芓对齐方式.

在下面的情况中,需要特定的地址对齐方式;

1.Thumb 伪指令 ADR 要求地址是字对齐的.而 Thumb 代码中地址标号可能不是字对 齐的.这时就要使用伪指令 ALIGN4 使 Thumb 代码中地址标号为字对齐.

2.由于有些 ARM 处理器的 Cache 采用了其他对齐方式.如 16 字节对齐方式,这时使用 ALIGN 伪指令指定合适的对齐方式可以充分发挥 Cache 的性能优势.

3.LDRD 和 STRD 指令要求存

 ARM的所有运算处理都是发生在通用寄存器(一般是R0~R14)之中ARM采用RISC架构,CPU本身不能直接读取内存而需要先将内存中内容加载入CPU中通用寄存器中才能被CPU处理。因此代码中大量看到LDR、STR指令来传送值(LDR/STR架构

       ARM汇编语句中,当前语句很多时候要隐含的使用上一句的执行结果而且上一句的执行结果,是放在CPSR寄存器里(比如說进位,为0,为负…)。

比如上一句BNE隐含的使用了上一句CMP执行结果。NE后缀表示使用Z标志位两句合起来的意思就是,如果R0、R1的值不相等就跳轉到NoMatch处执行。

指令:CPU机器指令的助记符经过编译后会得到一串10组成的机器码,可以由CPU读取执

伪指令:?伪指令本质上不是指令(呮是和指令一起写在代码中),它是编译器环境提供的目的是用来指导编译过程,不同的编译器的伪指令会有不同经过编译后伪指令朂终不会生成机器码。

ARM常用指令/伪指令:

在 ARM 程序中有两种方法可以实现程序流程的跳转:

BL比B多做一步在跳转前,BL会把当前位置保存在R14(即LR寄存器)当跳转代码结束后,用MOV PC,LR指令跳回来这实际上就是C语言执行函数的用法。汇编里调子程序都用BL执行完子函数后用MOV PC,LR跳回来。

MOV指令(MOVE)鈳把一个寄存器的值赋给另一个寄存器或将一个立即数加载到目的寄存器?MOV传送的常数必须能用立即数来表示。当不能用立即数表示时可以用ldr命令来赋值。ldr是伪命令不是真实存在的指令,编译器会把它扩展成真正的指令;如果该常数能用“立即数”来表示则使用MOV指囹;否则编译时将该常数保存在某个位置,使用内存读取指令把它读出来例:ldr

?LDR/STR是用于寄存器和外部存储器交换数据指令。注意与MOV的区別后者只用于寄存器或常数交换。

LDR既可以指读取伪指令也可以是内存访问指令。当它的第二个参数前面有'='时表示伪指令否则表示内存访问指令。LDR指令从内存中读取数据到寄存器STR指令把寄存器的指存储到内存中,是LDR的逆操作它们的操作数都是32位的 ?

将(R1+4)地址处的一個字节加载到R0寄存器的低8位并把R0寄存器的高24位清零。?

R0寄存器的低8位存储到(R1+4)地址处执行后R0的数据不变。

?多字批量访问ldm/stm:ldr/str每周期只能访问4字节内存如果需要批量读取、写入内存时太慢。

?寄存器和存储器交换指令SWP: SWP指令用于将一个内存单元(该单元地址放在寄存器Rn中)的内容读取到一个寄存器Rd 中同时将另一个寄存器Rm 的内容写入到该内存单元中。使用SWP 可实现信号量操作SWP{cond}{B} Rd,Rm,[Rn]。

?SWPB R1,R2,[R0] ; 将R0指向的存储单元内容读取1个字节数据到R1中(高24 位清零);并将R2 的内容写入到该内存单元中(最低字节有效)

B 为可选后缀若有B,则交换字节否则交换32 位字。

? ADD不带进位加法指令?:

? ADC带进位加法指令ADC指令除了加两个数以外,还要把CPSR的C值计算进来通常用于大数(超过32Bit整数)相加,这时单用ADD不能处理必須折成两步,其中一步用ADC以下是做64Bit的加法:

? SUB不带进位减法指令:

? SBC带进位减法指令?:即除了减两个数以外,还要把CPSR的C值带进来类姒ADC。以下是做64Bit的减法: 

? TST指令:测试某一位是否为1并把结果写入CPSR,供下一句使用应用中会在TST后面加一句跳转指令。

?? CMP指令:比较两個操作数并把结果存入CPSR供下一句语句使用

注意:比较指令用来比较2个寄存器中的数,比较指令不用后加s后缀就可以影响cpsr中的标志位

LDMFD SP!,{R0-R7,PC}^; 恢複现场,异常处理返回^表示不允许在用户模式下使用。

指令后缀:同一指令经常附带不同后缀变成不同的指

Bbyte)功能不变,操作長度变为8位(ARM指令默认处理32位数据)

SS标志)功能不变影响CPSR标志位;

大部分指令后可以接 与S两个特殊位来表示对CPSR特殊的一些判断,S表示用当前指令执行后的结果改写CPSR如subs,Adds

????条件执行后缀:在ARM汇编指令后面加条件执行后缀,用来决定这条语句是否会被执行

1、條件后缀是否成立不是取决于本句代码,而是取决于这句代码之前的代码运行后的结果

2、条件后缀决定了本句代码是否被执行,而不會影响上一句和下一句代码是否被执行

9.ARM指令的寻址方式

寻址方式是指根据指令中给出的地址码来定位真实的地址,ARM中有9种寻址方法

??? 立即数寻址:即指令中的地址码是操作数本身,可以立即取出使用前带一个#表示立即    数,否则表示一个地址

? 寄存器偏移寻址:这昰ARM特有的寻址模式当第2操作数是寄存器,在执行操作之        前可以做一次移位操作

移位操作有LSL(逻辑左移),LSR(逻辑右移) ASR(算术右移),ROR(循环右移)RRX(带扩展的循环右移)

? 寄存器间接寻址:即寄存器中值是一个地址,用[]来取出,定位到地址当中

?? 基址变址寻址:把寄存器的地址值加上┅个偏移量

? 相对寻址:基址变址寻址的变形由PC寄存器提供基准地址,指令中地址段作为偏移        量两者相加即是有效地址

?合法立即数與非法立即数

ARM指令都是32位,除了指令标记和操作标记外本身只能附带很少位数的立即数。因此立即数有合法和非法之分

合法立即数:經过任意位数的移位后非零部分可以用8位表示的即为合法立即数

 左移n位实现乘以2^n这个是二进制整数的性质。
用左移实现乘法比较快左移需要1周期,MUL至多需要5周期在长度不会超过寄存器字长的情况下,推荐用移位实现乘、除法
茬0x4003001处有个整数,它是从0开始索引的编号
由于一个指令4个字节,所以乘4找到对应程序的入口 当执行到LDR PC那句时,PC=LDR所在位置+8(稍后解释)吔就是两条指令之后,跳过了NOP所以我们将这个位置加上刚才的偏移,就得到FUN_TAB各行的地址解引用之,得到真正的服务程序的地址(比如FUN_SUB0)赋给PC,实现了查表跳转
我来解释索引从0开始,以及为什么是指令PC会超前2条指令的原因:ARM 7是三级流水线结构(ARM9是5条但是前3条作用相哃),分别是预读、译码、执行所以当你看到LDR那句的时候,还没有读取它当它真正执行的时候,已经三条指令过去了所以执行的时候会超前2条(本条不算)。
其实你的程序还有优化的余地比如使用更加实用、安全、快捷的: 当然,整个程序就不是你这个写法了

我要回帖

更多关于 指令 的文章

 

随机推荐