ARM有2种方法可实现程序的转移:
- 一种是利用传送指令直接向PC寄存器R15中写入转移的目标地址,通过改变PC的值实现程序的转移;
- 另一种就是利用转移指令。
ARM的转移指令可以从当前指令向前或向后的32MB的地址空间跳转,根据完成的功能它可以分为以下4种 :
- B 转移指令
- BL 带链接的转移指令
- BX 带状态切换的转移指令
- BLX 带链接和状态切换的转移指令
转移和转移链接指令(B,BL)
转移指令B在程序中完成简单的跳转指令,可以跳转到指令中指定的目的地址。BL指令完全象转移指令一样地执行转移,同时把转移后面紧接的一条指令的地址保存到链接寄存器LR(r14),这样可以实现子程序的返回。
二进制编码
跳转目标地址的计算方法:先对指令中定义的有符号的24位转移量用符号扩展为32位,并将该32位左移2位形成字的偏移,然后将它加到程序计数器PC中(相加前程序计数器的内容为转移指令地址加8字节)。一般情况下汇编器将会计算正确的偏移。
转移范围为±32MB。
L标志为1时,为转移连接指令。
汇编格式
L指定转移与连接属性,如果不包括L,便产生没有连接的转移。<cond>是条件执行的助记符扩展,缺省为AL,即无条件转移。<target address>一般是汇编代码中的标号,是转移到的目标地址。
举例:
(1)无条件转移
(2)执行10次循环
(3)调用子程序
注意:在子程序返回之前,不应再调用下一级嵌套子程序。
汇编语言子程序调用及返回
在ARM汇编语言中,子程序调用是通过BL指令来完成的。BL指令的语法格式如下:
其中,subname是被调用的子程序的名称。BL指令完成两个操作:将子程序的返回地址放在LR寄存器(r14)中,同时将PC寄存器值设置成目标子程序的第一条指令地址。
在返回调用子程序时,转移链接指令保存到LR寄存器(r14)中的值需要拷贝回程序寄存器PC(r15)。
(4)子程序的嵌套调用
为了实现子程序的嵌套调用,应该在调用嵌套子程序之前,先将R14内容压栈保存。如:
(5)条件子程序调用
注意:只有SUB1不改变条件,这里才能正常运行。
当转移指令转移到32MB地址空间之外时,将产生不可预测的结果。
转移交换和转移链接交换(BX,BLX)
这些指令用于支持Thumb(16位)指令集的ARM芯片,程序可以通过这些指令完成处理器从ARM状态到Thumb状态的切换。类似的Thumb指令可以使处理器切换回32位ARM指令。
在第一种格式中,寄存器Rm的值是转移目标,Rm的第0位拷贝到CPSR中的T位,进而决定是切换到Thumb状态还是ARM状态。[31:1]位移入PC。
如果Rm[0]是1,则切换到Thumb状态,并在Rm中的地址处开始执行,但需将最低位清0,使之半字对齐。
如果Rm[0]是0,则切换到ARM状态,并在Rm中的地址处开始执行,但需将Rm[1]清0,使之半字对齐 。
ARM的状态寄存器CPSR中的状态控制位T-bit(位[5])决定了当前处理器的运行状态,因此,可以通过MSR和MRS指令来直接修改CPSR的状态位,也能够改变处理器运行状态
但由于ARM采用多级流水线的结构,这样做会造成流水线上预取指令的执行错误,而如果用BX指令,则不会出现这样的问题
下面是一段直接进行状态切换的例程。
参考文献:
孟祥莲.嵌入式系统原理及应用教程(第2版)[M].北京:清华大学出版社,2017.