ARM汇编语言学习笔记

时间:2022-05-20 14:02:03

汇编是对寄存器操作的,不知道一些和主控制器相关的寄存器的作用,根本无法理解某些指令,所以先自己学习相关寄存器和工作模式。

下面是《ARM 嵌入式体系结构与接口技术(Cortex-A8 版) 》的学习笔记

ARM处理器相关寄存器:

ARM Cortex-A8 处理器有 40 个 32 位长的寄存器
(1)32 个通用寄存器。 
(2)7 个状态寄存器:1 个 CPSR(Current Program Status Register,当前程序状态寄存器),6个 SPSR(Saved Program Status Register,备份程序状态寄存器)。 
(3)1 个 PC(Program Counter,程序计数器)。

ARM汇编语言学习笔记

1.处理器模式和切换方法


这图是我在arm相关的芯片手册上找到的,在这里可以看到arm处理器有八种模式,system和user两种模式还用了相同的寄存器组。每种模式都有自己的专用的寄存器,但是有些寄存器是通用的,所以有些寄存器的名字相同但是实际上他们对应的可能在物理上不一定是一个位置,比如不同模式下的R6对应的实际位置是不同的。(学习汇编的时候遇到了相似的过程,后面会提到,这里先标记住),除了用户模式外的其他七种模式成为特权模式(Privileged Modes).在特权模式下程序可以访问所有的资源,也可以在任意的进行处理器模式的切换,大多数情况下程序都是运行在用户模式下的,在用户模式下应用程序不能访问受操作系统保护的一些资源也不能进行处理器模式的切换,需要切换的时候要么由应用程序产生异常处理,异常处理过程中进行处理器模式的切换

ARM汇编语言学习笔记


根据学习过程发现用到的irq模式比其他模式多。


Cortex -A8存储系统

ARM 存储系统有非常灵活的体系结构,可以适应不同嵌入式应用系统的需要。ARM 存储器系统可以使用简单的平板式地址映射机制(就像一些简单的单片机一样,地址空间的分配方式是固定的,系统中各部分都使用物理地址),也可以使用其他技术提供功能更为强大的存储系统。例如: 


(1)系统可能提供多种类型的存储器件,如 Flash、ROM、SRAM 等; 
(2)Cache 技术; 
(3)写缓存技术(Write Buffer); 
(4)虚拟内存和 I/O 地址映射技术。 


大多数的系统通过下面的方法之一可实现对复杂存储系统的管理:
(1)使用 Cache,缩小处理器和存储系统速度差别,从而提高系统的整体性能。 
(2)使用内存映射技术实现虚拟空间到物理空间的映射。这种映射机制对嵌入式系统非常重要。

通常嵌入式系统程序存放在 ROM/Flash 中,这样系统断电后程序能够得到保存。但是,ROM/Flash 与SDRAM 相比,速度慢很多,而且基于 ARM 的嵌入式系统中通常把异常中断向量表放在 RAM 中。利用内存映射机制可以满足这种需要。在系统加电时,将 ROM/Flash 映射为地址 0,这样可以进行一些初始化处理。当这些初始化处理完成后将 SDRAM 映射为地址 0,并把系统程序加载到 SDRAM 中运行,这样能很好地满足嵌入式系统的需要。 
(3)引入存储保护机制,增强系统的安全性。 
(4)引入一些机制保证将 I/O 操作映射成内存操作后,各种 I/O 操作能够得到正确的结果。在简


单存储系统中,不存在这样问题。而当系统引入了 Cache 和 Write Buffer 后,就需要一些特别的措施。 在 ARM 系统中,要实现对存储系统的管理通常是使用协处理器 CP15,它通常也被称为系统控制协处理器(System Control Coprocessor)。 ARM 的存储器系统是由多级构成的,可以分为内核级、芯片级、板卡级、外设级。图 2-4 所示为存储器
的层次结构。每级都有特定的存储介质,下面对比各级系统中特定存储介质的存储性能。 

ARM汇编语言学习笔记

特点:越网上空间越小,读取写入速度越快,价格越来越昂贵,CP15后面会介绍相应的汇编指令和寄存器。

协处理器


ARM 处理器支持 16 个协处理器(CP15)

执行过程:

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

作用:

CP15,即通常所说的系统控制协处理器(System Control Coprocesssor),负责完成大部分的存储系统管理。除了 CP15 外,在具体的存储管理机制中可能还会用到其他的一些技术,如在 MMU 中除了 CP15 外,还使用了页表技术等。 在一些没有标准存储管理的系统中,CP15 是不存在的。在这种情况下对 CP15 的操作指令将被视为未定义指令,指令的执行结果不可预知。 CP15 包含 16 个 32 位寄存器,其编号为 0~15。实际上对于某些编号的寄存器可能对应多个物理寄存器,在指令中指定特定的标志位来区分这些物理寄存器。这种机制有些类似于 ARM 中的寄存器,当处于不同的处理器模式时,某些相同编号的寄存器对应于不同的物理寄存器。 CP15 中的寄存器可能是只读的,也可能是只写的,还有一些是可读可写的。在对协处理器寄存器进行操作时,需要注意以下几个问题。(作用是完成存储系统管理

注意事项

(1)寄存器的访问类型(只读/只写/可读可写)。 
(2)不同的访问引发不同功能。 
(3)相同编号的寄存器是否对应不同的物理寄存器。 
(4)寄存器的具体作用。

具体见后面相关汇编指令。

程序状态计数器:

这个比较重要,包含了很多重要信息,32位寄存器。包括SPSR和CPSR,前者是备份的,后者是当前的。

ARM汇编语言学习笔记

  1. N:本位设置成当前指令运行结果的 bit[31]的值。当两个由补码表示的有符号整数运算时,N=1 表示运算的结果为负数;N=0 表示结果为正数或零。
  2. Z:。Z=1 表示运算的结果为零,Z=0 表示运算的结果不为零。
  3. C:加法溢出时候产生进位为1,平时为0,减法相反,其他操作不影响,移位操作时候被设置成最后移出的位。
  4. V: 对于加减法指令V=1时候表示有符号溢出,非加减法不受影响。
  5. 模式控制[4:0]
  6. ARM汇编语言学习笔记
  7. IF-THEN标志位(这里不太懂,没见到用过)这些位是bit 15 :10 26:25
  8. 控制位:I表示IRQ中断,F表示FIQ中断,表示1表示禁止。,T=0表示Thumb状态,如果为1表示ARM状态。
  9. 其他的位:表示异步异常禁止,大小端控制,大于小于标志什么的,也没有见到用过

ARM微处理器的指令系统

ARM指令的分类

根据作用分: 跳转指令,数据处理指令,程序状态寄存器传输指令,LOAD/STORE指令,协处理器指令和异常中断产生指令。 寻址方式分: 数据处理指令寻找方式,内存访问指令寻址方式

ARM处理器的寻址方式

在我看了如果汇编是英语的话,这些就是一些基本的语法,句型。实际会通过语句来体现,在汇编里面就是指令。汇编语言无疑就是寄存器与寄存器之间的数值交换, 复制等运算,相互捣鼓,寻址方式是如何找到相应的操作的数或者正确的寄存器。

数据指令寻址方式

这些都是根据数据如何在寄存器取出有关的

立即数寻址

一个汇编指令最多32位,在立即数寻找方式中,由一个8bit的常数移动4bit偶数位,每个指令包含了一个8bit的常数位X和一个4bit的移位值Y, 立即数=X循环右移动(2*Y) 在立即数里面不是所有的书都是合法的,可以通过上述规则得到的就是合法否则不是合法的。例如0xFF合法,0x101不合法。 指令举例: MOV R0,#0; ADD R3,R1,#1

寄存器寻址

寄存器的值可以直接被用于数据操作指令 例如: ADD R2,R1,R0

寄存器移位寻址

寄存器的值在进行运算之前可以先进行移位,预处理和移位发生在一个机器周期内,有效使用移位可以提高效率 ADD R2,R0,R1,LSR #5

内存访问指令

字及无符号字节的Load/store指令寻找方式

格式LDR|STR {<cond>}{B}{T} <RD>,<addressing_mode>,这类指令就是把寄存器里面的存的数当成一个内存地址,然后对这个内存地址的操作 <addressing_mode>有九中方式,几种常用的 [Rn,#+-<offset_12>]把Rn里面的值当成一个地址+(-)offset_12,然后对这个地址的数进行操作。其他的都可以理解,实际的汇编中见到的很容易理解, 重点是如果在<addressing_mode>后面有“!”,表示完成数据后要更新机制寄存器,也就是上面指令提到的Rn,这类指令里面东陵路是一个基址寄存器,后面进行相应的偏移量操作的。

杂类Load/Store指令寻址方式

这里指令包含了有符号/无符号半字Load/Store指令,有符号字节Load/store指令和双字Load/store指令。和第一种结合起来就全了。寻找方式6种没什么区别一看就会。

批量Load/Store寻址方式

这类寻址方式很常见,貌似也很重要,进行栈保存和函数返回的时候经常见到。主要作用是将连续的内存的数据保存到寄存器或者把一组通用寄存器的内容加载到连续的内存单元。 格式:LDM|STM{<cond>}<addressing_mode> <Rn>{!},<registers><^>
LDM和STM后面可以加相应的后缀,表示不同的操作类型。 IA,后递增方式。 IB,先递增方式。 DA,后递减方式。 DB,先递减方式。 LDMIA   R0,  {R1,R2,R3,R4}  ;R1 <- [R0],R2 <- [R0 + 4],R3 <- [R0 +8],R3 <- [R0 + 12],这是后递增,根据这里理解其他三种就不难了。

堆栈操作寻找方式

这个和前面一种用到的有点类似,对于堆栈的操作,数据写入内存和从内存中读取使用不同的寻找模式,因为进栈操作和出栈操作,要在不同方向上调整堆栈。
有四种模式,就是把上面的LDM|STM的后缀换了:
  1. full栈:堆栈指针指向栈顶元素。
  2. empty栈:堆栈指针指向第一个可用元素
  3. 递减栈:堆栈指针指向内存小的方向增长。
  4. 递增栈:堆栈指针指向内存地址增大的方向增长。
根据堆栈类型分:
  1. 满递减FD
  2. 空递减ED
  3. 满递增FA
  4. 空递增EA

协处理器指令

<opcode>{<cond>}{L},<CRd>,<addressing_mode>

ARM处理器的指令集



如果说前面是英语的语法规则,指令集就好比英语中的单词,根据相应的单词有表达不同的意思,对于CPU就是不同的操作。

指令格式

ARM汇编语言学习笔记
<opcode>    {<cond>}    {S}     {Rd},    {Rn},    {shifer_operand}
  • <opcode>:    指令操作符编码,如 LDR、STR 等。
  • {<cond>}:    指令执行的条件编码,如 EQ、NE 等。
  • {S}:  决定指令的执行是否影响 CPRS 的值。
  • {Rd}:  目标寄存器编码。
  • {Rn}:    包含第一个源操作数的寄存器编码。
  • {{shifer_operand}:  第二个操作数

条件码


如下图,根据程序状态寄存器的位进行组合得到, ARM汇编语言学习笔记

ARM指令大全

数据操作指令

1.MOV指令:

格式:mov    {<cond>}    {S}     {Rd},    {Rn},    {shifer_operand}

作用:
  • 将数据从一个寄存器传送到另一个寄存器MOV R0,R1
  • 将一个常数值传送到寄存器MOV R0,#3
  • 实现无算数和逻辑运算的单纯移位操作,MOV R0,R0,LSL#3
  • 当PC用作目的寄存器的时,实现程序的跳转,MOV PC,LR
  • PC作为目标寄存器指令中S被设置时候,MOVS PC,LR,可以实现某些从某些异常中断返回。

2.MVN指令

和mov指令相似,只不过传送的是操作书的反码
作用:
  • 向寄存器传送一个负数
  • 生成位掩码
  • 求一个数的反码
举例:
MVN R0,#4; 4用二进制表示可以00100,取反得11011,第一个1是符号位,结果是-5.

3.AND指令

格式AND   {<cond>}    {S}     {Rd},    {Rn},    {shifer_operand} 表示shifter_operand 表示的数值和Rn值按位与,把结果保存在Rd.

4.EOR指令

同上,按位异或

5.SUB指令

同上,相减。

6.RSB指令

从shifter_operand中减去Rn表示的数值,并将结果保存在目标寄存器Rd里面。
举例:求一个64位数的负数,64位数放在寄存器R0和R1,其负数放在R2,R3,其中R0和R2放低32位的值。
RSBS R2,R0,#0; RSC R3,R1,#0; 假设一个64位数表示的是1,R0:31位是0,最低位是1,R1全都是0,第一个指令操作后,用0减去1,后缀有S,最终导致 R2所有的位都是1,并且CPSR里面C位变成了0,第二个指令是RSC这里表示是带借位的翻转减,所以,R3=0-R1+ C-1导致R3最终里面的书全部都是1,把R2和R3结合起来当成一个有符号数计算结果是-1.                                                                                                                                                                                                             

7.ADD指令

加指令,例如:ADD R0,R1,R2.ADD R0,R1,R3,LSL#1

8.ADC指令

Rd=Rn+op2+C 带进位的加,shifter_operand的值+Rn表示数值再加上CPSR为的C的值,将结果保存到寄存器Rd。
举例相加两个128位的数: 第一个128位的数,R4,R5,R6,R7,第二个128位的数:R8,R9,R10,R11; ADDS R0,R4,R8; ADCS R1,R5,R9, ADCS R2,R6,R10 ADCS R3,R7,R11

9.SBC指令

Rd=Rn-op1+c-1

用于执行32位的指令减法操作,代表位的减。

例子:

实现64位的减法

SUBS R0,R0,R2

SBCS R1,R1,R3

10.RSC指令

带进位的翻转减,Rd=op2-Rn+C-1.

11.TST指令

格式TST {<cond>}<Rn>,<shifter_operand>,用于一个寄存器的值和一个操作数进行比较忙,条件标志位根据两个操作数做“逻辑与”运算后设置。TST指令类似与CMP指令,不产生放置目标寄存器的结果 ,而是给出的两个操作数上进行操作并把结果反应在状态标志上,使用TST指令来检查是否设置了特定的位。

操作数2当成一个位掩码,测试后如果结果匹配设置zero标志位,否则清除它。这个指令不用制定S后缀。

例子:

TST R0,#1,检测R0里面是否设置了位0.

12.TEQ指令

用于将一个寄存器的值和一个算数值做比较,条件码根据两个数做逻辑异或后的结果进行设置,一变后面的指令根据相应的条件标志位判断是否执行。

13.CMP指令

CMP {<cond>} <Rn>,<shifter_operand>.

用法用Rn-shifter_operand根据结果更新CPSR相应的条件标志位来运行进行条件执行,它虽然进行一次减法运算但是不储存运算结果,而是正确的更改标志位,所以和SUBS

指令是不一样的,标志位表示的是运算结果。大于小于等于都是可能的,如果大于,后面的后GT后缀的指令会执行。

14.CMN指令

CMN {<cond>} <Rn>,<shifter_operand>
根据Rn+shifter_operand的结果设置标志位,和CMP操作对CPSR条件标志位有细微影响。 当第二个操作数是0或者0x80000000时候,结果不同。 例如CMP Rn,#0,CMN Rn,#0 第一个指令使得标志位C值为1,第二条指令使得标志位C取0.

15.ORR指令

逻辑或操作

16.BIC位清零指令

BIC {<cond>} {S}<Rd>,<Rn>,<shifter_operand>
将寄存器Rn的值和第二个源操作数shifter _operand的值的反码按位取“逻辑与操作”运算结果保存到Rd里面。
BIC R0,R0,0xb,清除0,1,3位,其余不变。就是指定哪个位为1,把那个位清零

乘法指令

arm乘法指令完成两个数据的运算,两个32位的二进制数相乘的结果是64位的积,有些arm版本将乘积的结果保存在两个独立的寄存器,有些只把最低有效32位存放在一个寄存器对于只保存32位的乘法指令,不需要区分有符号还是无符号。

1.MUL指令

MUL {<cond>}{S} <Rd>,<Rm>,<Rs> 32位乘法指令将Rm和Rs相乘,结果的最低32位保存在Rd。

2.MLA指令

MLA {<cond>}{S} <Rd>,<Rm>,<Rs>,<Rn> 32位乘-累加指令将Rm和Rs中的值相加,在将乘积加上第三个操作数,结果的低32位保存在Rd里面。

3.UMULL指令

UMULL{<cond>}{S} <RdLo>,<RdHi>,<Rm>,<Rs> 64位无符号乘法指令,将Rm和Rs的值做无符号数相乘,结果的低32位保存在RsLo里面,高32位保存在RdHi里面。


4.UMLAL指令

UMLAL{<cond>}{S} <RdLo>,<RdHi>,<Rm>,<Rs>
64位无符号长乘累加指令,先相乘然后把这个64位数和RdHi,RdLo相加,其他和上面一样。

5.SMULL

64位有符号长乘指令,参考UMULL。

6.SMLAL

64位有符号数长乘累加指令,参考UMLAL

Load/Store指令

这类指令用于在ARM寄存器和存储器之间传数据,具体的在前面的arm指令的内存寻址方式可以看出不同操作数寻找方式。
  • 单寄存器Load/store指令,这类指令在ARM寄存器和存储器之间提供更灵活的单数据传送方式,数据项可以是字节。16位半字,32位字
  • 多寄存器内存访问指令,灵活性比单寄存器指令差,但可以大量传送数据,用于进程的进入和退出,保存和回复工作寄存器和复制存储器中的一块数据。
  • 单寄存器交换指令,允许寄存器和存储器之间的数据进行交换,用到少,用来实现信号量操作。

单寄存器Load/Store指令

1.LDR指令

从内存中讲一个32位的字读取到目标寄存器。 例如:LDR R1,[R2]

2.STR指令

将一个32位的字数据写入内存。 用途:变量访问,GPIO设置,程序散转

3.后缀说明

B表示操作的是最后一个字节,H表示的是低16位,没有后缀表示32位

多寄存器load/store访问指令

1.LDM指令


将数据从连续的内存单元中读取到指令中指定的寄存器列表中的各寄存器,当PC包含在寄存器列表时候,指令从内存读取的字数据被作为目标地址值,指令执行后程序从目标地址处开始执行,实现了指令的跳转。寄存器R0~R15分别对应指令编码的bit ['0]~bit[15]位,如果Ri存在寄存器列表,相应的位为1,否则为0,LDM指令将数据从连续的内存单元读取到指令中指定的寄存器列表中各寄存器。 LDM{<cond>}<addressing_mode> <Rn>{!},<registers>

LDM{<cond>}<addressing_mode> <Rn><registers_without_pc>

2.STM指令

STM指令将指令中寄存器列表的各寄存器数值写入到连续的内存单元,主要用于块数据的写入,数据栈操作及子程序进入时保存相关寄存器等操作。
STM{<cond>} <addressing_mode> <Rn>{!},<registers>
STM{<cond>} <addressing_mode> <Rn>,<registers>^

3.数据传送指令应用 LDM/STM批量加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据,LDM为加载多个寄存器,STM为存储多个寄存器,允许一条指令传送16个寄存器的任何子集或所有的寄存器。
LDM{cond}<模式> Rn {!},regist{^} STM{cond}<模式> Rn {!},regist{^}
模式在堆栈操作寻址方式批量load/store存储方式可以看到。
注意:
  1. Rn不允许是R15,Rn是基址寄存器,装有传送数据的初始地址。
  2. “!”表示最后的地址要写会Rn
  3. 寄存器列表regist可以包含一个或者寄存器范围,用“,”分开,范围用“~”表示,寄存器按照大小排列
  4. “^"后缀不允许在用户模式下使用,只能在系统模式下使用"^"进行数据传送且寄存器列表不包含PC时候,加载存储的是用户模式寄存器而不是当前模式寄存器。
  5. LDM指令的寄存器列表包含有pc时使用,除了正常的多寄存器传送外,将SPSR赋值到CPSR,用于异常处理返回

这类指令经常见到,如下:
LDMIA R0!,{R3~R9} ;加载R0指向的地址上的多字数据,保存到R3~R9里面。R0值更新。 STMIA R1!,{R3,R9} ;将R3~R9的数据存储到R1指向的地址上,R1值更新。 STMFD SP!,{R0~R7,LR}现场保存,将R0~R7,LR入栈。 LDMFD SP!,{R0~R7,PC}^;恢复现场,异常处理返回;

单数据交换指令

SWP{<cond>} <Rd>,<Rm>,[<Rn>] 假设内存单元地址存放在寄存器Rn里面,指令将<Rn>里面的数据读取到目的寄存器Rd,同时另一个寄存器<Rm>的内容写入到内存单元。当Rd和Rm是同一个寄存器时候指令交换该寄存器和内存单元的内容。

跳转指令

1.B/BL指令

B{L}{<cond>} <target_address> 跳转B和跳转连接BL指令是改变指令执行顺序的标准方式调用函数的时候会用到。
跳转指令可以使得程序转到制定的地址执行程序,带连接的跳转指令BL将下一条指令的地址复制到R14,这两条指令都可以根据CPSR中的条件标志位的值决定指令是否执行。
BL指令用于实现子程序的调用,子程序的返回可以通过将LR寄存器的值复制到PC来实现
实现程序返回的指令
  • BX R14
  • MOV PC,R14
  • 在子程序入口处使用压栈指令:STMFD R13,{<registers>,R14}

LDMFD R13!,{<registers>,PC},把子程序放入PC中
程序实例:
B LABLE;  跳转到LABEL ADD R1,R2,#4; LABLE: SUB R1,R2,#8 
B 0x1234 跳转到绝对地址0x1234
BCC LABLE 当CPSR寄存器的C条件标志位为1时候,程序跳转到标号LABLE出

2.带状态切换的BX指令

带状态切换的跳转指令,使程序跳转到指令中指定的参数Rm指定的地址执行程序,Rm的第0位赋值到CPSR中T位,bit[31:1]移入PC,若Rm的bit[0]为1,则自动将CPSR中标志位T置位,把目标代码解释为thumb代码,若Rm的bit[0]为0,则跳转时自动将CPSR中的标志位T复位,把目标代码解释为ARM代码。(在arm和thumb状态间切换)
指令语法格式:BX{<cond>} <Rm>
当Rm[1:0]=0b10时,之类的执行结果不可预知,因为ARM状态下,指令是4字节对齐的
PC可以作为Rm寄存器使用,当PC作为<Rm>使用时,BX PC将程序跳转到下面的第二条指令处执行。

BX R0;转移到R0中地址,如果R0[0]=1,进入Thumb状态

3.带连接和状态切换的连接跳转指令BLX

带连接和状态切换的跳转指令,用于程序跳转到Thumb状态或者从Thumb状态。该指令为无条件执行指令,并用分支寄存器的最低位来更新CPSR中的T位,将返回地址写入到 连接寄存器LR。

状态操作指令

1.MRS指令

格式 MRS {cond}Rd,其中为目标寄存器,Rd不允许为程序计数器,PSR为CPSR或SPSR。在ARM处理器中,只有MRS指令可以将状态寄存器CPSR活SPSR读出到通
用寄存其中。将CPSR或者SPSR读出到通用寄存器中。
MRS R1,CPSR;将CPSR状态寄存器读取,保存到R1 MRS,R2,SPSR ;将SPSR状态寄存器读取,保存到R2
这个指令可以判断里面的标志为,根据标志位的情况判断相应的状态和操作是否允许,进程切换或允许异常中断嵌套时,也需要MRS指令读取SPSR状态值并保存起来。

2.MSR指令

这是唯一一个可以直接设置状态寄存器CPSR或者SPSR的指令
MSR {cond} PSR_field,#immed_8r MSR {cond} PSR_filed,Rm 其中PSR是指CPSR或者SPSR ,<fields>设置状态寄存器要操作的位,状态寄存器的32位分成4个8位的域,见到很多次
  • bits[31:24]为条件标志域,用f表示
  • bits[23:16]为状态标志域,用s表示
  • bits[15:8]为扩展域,用x表示
  • bits[7:0]为控制域,用c表示


只有在特权模式下才可以修改状态寄存器
举例:MSR_C,#0xD3,切换到管理模式
程序里不能通过MSR指令修改CPSR里T位控制实现ARM状态/Thumb状态的切换,必须使用BX指令完成处理器的状态切换,BX指令属于转移指令,会打断流水线的状态,实现处理器的状态切换,MRS与MSR配合使用,实现PSR读-修改-写操作,用来进行处理器模式的切换及允许/禁止IRQ/FIQ中断设置等。
程序状态寄存器指令应用:
ENABLE_IRQ:               使能IRQ中断 MRS R0,CPSR BIC R0,R0,0x80 MSR CPSR_c,R0 MOV PC,LR

协处理指令

  1. 协处理器数据操作
  2. 协处理器数据传送
  3. 协处理器寄存器传送

MCR/MRC


如果没有协处理器执行指定操作的产生未定义异常
MCR{<cond>} <coproc>,<opcode_1>,<Rd>,<CRn>,<CRm> {<opcode_2>}
<cond>条件域,指定条件,否则无条件执行 <coproc>指定协处理器编号,p0..p15
<opcode_1>指定协处理器执行的操作码,确定哪一个协处理器指令被执行 <Rd>确定哪一个ARM寄存器的数值被传送 <CRn>确定包含第一个操作数的协处理器寄存器 <CRm>确定包含第二个操作数的协处理器寄存器 <opcode_1>确定协处理器执行的操作码,确定哪一个协处理器指令被执行,通常和<opcode_1>配合使用
指令举例:将ARM寄存器R7的值传送到协处理器p14的寄存器c7里面,第一操作数是1,第二个是6。 MCR  p14,1,r7,c7,c12,6
MRC作用相反,协处理器指令感觉不是重点,以后不会了重新来!

异常产生指令

SWI软件中断指令

作用产生软中断,实现用户模式到管理模式(感觉重要)
SWI {<cond>} <immed_24>
SWI 0;产生软中断,中断立即数是0

使用SWI指令时,传递参数的方法

  • 指令的操作数是个24位的立即数,指定了用户请求类型,中断服务程序的参数通过寄存器传递。
MOV R0,#34 设置功能号34 SWI 12 产生软中断,中断号12
  • 指令中24位数被忽略,用户请求的服务类型由寄存器R0值决定,
MOV R0,#12;设置12号软中断 MOV R1,#34;设置功能号34 SWI R0;

ARM伪操作

有的时候完成一个操作在不同的场合用不同的语句,为了方便,可以用伪指令,真正运行的时候将伪指令按照实际需要翻译为相应的汇编指令

1.ARM支持的伪指令

1.ADR伪指令
ADR {cond}{.w} register,label
ADR范围地址读取伪指令。
cond可选执行条件,W指定指令宽度,Thumb-2指令集支持,register,寄存器,label基于PC或者具体寄存器的表达式,这个指令可以使用add指令或者sub指令来实现功能。
例子:ldr r4,=data+4*n
2.ADRL伪指令
和ADR相似,只是范围更大,真正被编译成两条指令,所以范围大。
2.LDR伪指令
装载一个32位常数到寄存器
LDR{cond}{.W} register,=[expr|label-expr]
expr:32位常量表达式
label-exper是一个程序相关或声明为外部的表达式,汇编器将label-expr放入数据缓冲池,使一条程序相关的LDR指令将此值取出放入寄存器。
label-expr被声明为外部表达式,汇编器在目标文件插入链接重定位伪操作,由链接器在链接时生成地址。
当数据超过MOV和MVN范围时可以用这个指令,传输的是绝对地址。

GUN ARM支持的伪操作

这类伪操作,写这博客的时候目前还没见过

1.数据定义伪操作

用于为特定的数据分配单元,也可以完成已经分配的单元的初始化。
常见的有 .byte .short .long .float .string .asciz .sacii .rept .quad
.quad 定义八个字节的数据  .string和.asciz和.sacii一样都是定义多个字符串,.ascii要加‘\0' .rept 重复定义伪操作 .equ/.set赋值语句,

2.汇编控制伪操作

.if .else .endif  根据条件成立选择执行某个序列,和C语言一样
.macro 伪操作可以将一段代码定义为一个整体,成为宏指令,然后在程序通过宏指令多次调用这段代码。常用语代码较短但是参数较多情况,在.macro和.endm之间的指令序列称为宏定义体。
格式:
.macro
{$label}macroname{$parameter{,$parameter}...}
;code
.endm

以后见到在另外记录