欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

嵌入式系统(三):ARM 指令汇编(4)

程序员文章站 2022-03-16 17:16:52
...

(2)(3)中介绍了ARM处理区的存储访问指令,数据处理指令,分支指令,协处理器指令等,本文对其余的指令及注意事项做一补充

(5)杂项指令

在ARM指令集中杂项指令共有3条,它们非常重要,特别是与操作系统的使用息息相关:

1.软件中断产生指令:SWI
2. 程序状态寄存器读指令:MRS
3. 程序状态寄存器写指令:MSR

① 软中断指令“SWI”

SWI指令用于产生软中断,主要用于用户程序调用操作系统的系统服务。执行该指令后,处理器将完成以下动作:

  1. 切换到管理模式(操作系统使用的保护模式)
  2. 将CPSR备份到管理模式下的SPSR寄存器-也就是保存当前工作状态
  3. 程序跳转到软件中断入口
    嵌入式系统(三):ARM 指令汇编(4)
    1.使用操作系统后,为了防止出错的任务影响其它任务的执行,通常将任务放在用户模式执行,以限制其权限;
    2.对于一些重要的操作,如中断的开关,必须由操作系统完成。使用软件中断指令即可完成系统功能调用;

i.参数传递

SWI有两种参数传递的方式
指令中的24位立即数指定了用户请求的服务类型,参数通过通用寄存器传递。 (最常用)

MOV    R0,#34		;设置子功能号为34 
SWI    12		;调用12号软中断 

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


MOV    R0,#12		;调用12号软中断 
MOV    R1,#34		;设置子功能号为34 
SWI    0 

ii.执行过程

在SWI异常中断处理程序中,取出SWI指令中立即数的步骤为:
嵌入式系统(三):ARM 指令汇编(4)
1、CPSR的第六位即工作状态位,如果是1就是thumb指令,0即ARM指令。此时CPSR的内容已经复制到SPSR了。

2、【LR,#-2】是寄存器间接寻址,将-2加到LR上,取[LR-2]位置的操作数。

② 状态寄存器读指令“MRS”

在ARM处理器中,只有MRS指令可以对状态寄存器CPSR和SPSR进行读操作。通过读CPSR可以了解当前处理器的工作状态。读SPSR寄存器可以了解到进入异常前的处理器状态。指令格式如下所示:
嵌入式系统(三):ARM 指令汇编(4)

        应用示例:
    MRS    R1,CPSR	    ; 读取CPSR状态寄存器到R1
    MRS    R2,SPSR	    ; 读取SPSR状态寄存器到R2

SPSR: 在每种异常模式下都有一个程序状态寄存器SPSR, SPSR用于保存CPSR状态,以便异常返回后恢复异常发生时的工作状态

③ 状态寄存器写指令状态寄存器写指令“MSR”

在ARM处理器中,只有MSR指令可以对状态寄存器CPSR和SPSR进行写操作。与MRS配合使用,可以实现对CPSR或SPSR寄存器的读-修改-写操作,可以切换处理器模式等操作。使用时必须**精确到域,**取相应位数的数值进行写。
嵌入式系统(三):ARM 指令汇编(4)
嵌入式系统(三):ARM 指令汇编(4)
嵌入式系统(三):ARM 指令汇编(4)

(6)伪指令

ARM伪指令不属于ARM指令集中的指令,是为了编程方便而定义的。伪指令可以像其它ARM指令一样使用,但在编译时这些指令将被等效的ARM指令代替
嵌入式系统(三):ARM 指令汇编(4)

ARM伪指令有四条:
1.小范围地址读取指令:ADR
2.中等范围地址读取指令:ADRL
3.大等范围地址读取指令:LDR
4.空操作指令:NOP

① ADR伪指令

ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令,若不能用一条指令实现,则产生错误,编译失败。
嵌入式系统(三):ARM 指令汇编(4)

② 中等范围地址读取

ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址。在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令(ADR只有一条)。若不能用两条指令实现,则产生错误,编译失败。
嵌入式系统(三):ARM 指令汇编(4)

③ 大范围地址读取

LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。
嵌入式系统(三):ARM 指令汇编(4)

④ 空操作伪指令“NOP”

NOP伪指令在汇编时将会被代替成ARM中的空操作,比如可能是“MOV R0,R0”指令等。NOP可用于延时操作。

1.请使用NOP伪指令、比较指令、条件跳转指令等完成一个软件延时子程序,
延时长度由R0寄存器的数值控制?
Delay
       NOP		 ;空操作
       NOP
       NOP
       SUBS    R0,R0,#1 	 ;循环次数减一
       BNE      Delay	 ;如果循环未结束,跳转Delay继续
       MOV     PC,LR	 ;子程序返回

3.地址对准

所谓对齐就是数据在存储器中存放的规则,32位系统中一般有字节对齐(8bit)、半字对齐(16bit)、字对齐(32bit)三种方式,分别对齐到连续地址、偶数地址、被4整除的地址。

ARM体系结构中有ARM指令集和Thumb指令集2种,其中ARM指令为32位指令,按照4字节对齐存储,一条指令必须从4的整数倍地址来取;Thumb指令为16位指令,按2字节对齐存储,一条指令必须从偶数地址来取。

当如果一个字访问的地址是0x0003时,此时为非地址对准,将产生数据异常。

程序中可以使用一些措施保证地址对准,最方便的方法就是使用地址对准伪指令ALIGN;除此以外,也可以填充空指令NOP,空指令NOP被编译成2字节。

Cortex-M3虽然支持非对准的地址访问,但是只对下列指令可以:LDR,LDRT,LDRH,LDRHT,LDRSH,LDRSHT,STR,STRT,STRH,STRHT;而对于其他指令仍然不支持非对准的访问。因此需要注意地址对准的应用,不可以随意使用非地址对准方法。

4.位段操作

Cortex-M3也可以实现位的操作,但并不是所有的存储区域都可以实现位操作,只有两个位操作区,也称为位域。
嵌入式系统(三):ARM 指令汇编(4)

5.地址的前缀和后缀

①LDR R2,[R3,#0x30]     ②LDR R2,[R3],#0x30
③LDR R2,[R3,#-0x20]    ④LDR R2,[R3],#-0x20
⑤LDR R2,[R3,#0x20+0x20/2]   ⑥LDR R2,[R3],#0x20*4-0x10

第1条语句是地址前缀,这个前缀的含义是把R3+0x30地址处的数据加载给R2,注意先把R3加0x30;第2条语句是后缀,这个后缀的含义是把R3地址处的数据加载给R2,然后计算R3=R3+0x30,注意后把R3加0x30。前缀是不改变值的(想要改变必须加感叹号),后缀的地址是寄存器指向的地址,地址传输后再修改寄存器的值。

6.指令可选后缀-S后缀

S后缀的含义是:使用S后缀时,指令执行后程序状态寄存器的条件标志位将刷新;不使用S后缀,指令执行后程序状态寄存器的条件标志位将不发生变化。

指令举例如下:
    ADD R1,R2,R3
    ; 没有使用S后缀,条件标志位不刷新
    ADDS R1,R2,R3    
    ; 使用S后缀,条件标志位刷新

有些指令不需要加S后缀,在执行时同样刷新条件标志位,如比较指令CMP、CMN、测试指令TST等。
S后缀使用目的:在需要对条件进行测试,例如:是否有溢出,是否有进位,是否大于或小于等。

7.!后缀

!后缀的含义是:在指令的地址表达式中含有!后缀时,指令执行后,基址寄存器中的地址将发生变化,变化的结果如下:

指令举例如下:
LDR R2,[R1,#02]     
;没有!后缀,结果是把R1加2作为地址指针存储的数据赋给R2,R1值不变
LDR R2,[R1,#02];!后缀,结果是把R1加2作为地址指针存储的数据赋给R2,R1加2的结果送到R1中

8.B后缀和H后缀

B后缀的含义是:指令所涉及的数据是一个8位字节,不是一个字或半字。
H后缀的含义是:指令所涉及的数据是一个16位半字,不是一个字或字节。
指令举例:

LDR  R2,[R0,#20]       ;R2<-[R0+0x20]传送一个32位字
LDRB R2,[R0,#20]       ;R2<-[R0+0x20]传送一个8位字节
LDRH R2,[R0,#20]       ;R2<-[R0+0x20]传送一个半字

四、总结

  1. ARM处理器的寻址方式
    ——共有9种寻址方式;
  2. ARM指令的特点
    ——可条件执行、可选择影响标志位、具有非常灵活的第二操作数;
  3. ARM指令的种类,它能完成哪些功能
    ——共有7类指令,可以完成存储器访问、数据运算、程序跳转、处理器控制、以及帮助编程的伪指令等。

一个应用实例

      MOV R0,#0x500   	(R0: 0x500:0000 1001 0000 0000)
      ADD R1,R0,#0x06    (R1=R0+0x06=0000 1001 0000 1100)注意0x06的表示,前导0可以省略
      AND R2, R0,#0x07   (R2=0x500&0x0007=0)
      LDR R3,=0x12345678 (R3=0x12345678)
      STR R3,[R0]        (R3的内容存储到R0所在地址,R3有多个字节,遵循小断模式,以R0指向地址为起点,低位字节排放在内存的低地址端,见下图)
      LDRB R4,[R0,#2]    (R4=[R0+2]=[0x502]=0x34)
      LDRB R5,[R0]       (R5=[R0]=0x78)

嵌入式系统(三):ARM 指令汇编(4)

五、THUMB指令

Thumb指令集可以看作是ARM指令压缩形式的子集,它是为减小代码量而提出的,具有16位的代码密度。Thumb指令体系不完整,只支持通用功能。必要时仍需要使用ARM指令,如进入异常时。
Thumb指令集较ARM指令集有如下限制:
只有B指令可以条件执行,其它指令都不能条件执行;
分支指令的跳转范围有更多限制;
数据处理指令的操作结果必须放入其中一个操作数寄存器中,而不是第三个寄存器;
单寄存器访问指令,只能操作R0~R7;
LDM和STM指令可以对R0~R7的任何子集进行操作;

相关标签: 嵌入式系统