在ARM 指令集中已介绍过的多种形式分支指令和转移链接指令,以及用于ARM 和Thumb 状态切换的跳转指令,这里主要讲述Thumb 指令集的分支指令和转移链接指令,着重介绍二者的不同之处。
ARM 指令有一个大的(24 位)偏移域(offset field),这不可能在16 位Thumb 指令格式中表示。 为此,Thumb 指令集有多种方法实现其子功能。
Thumb 转移指令二进制编码如图4.3 所示。
转移指令的典型用法有:①短距离条件转移指令可用于控制循环的退出;②中等距离的无条件转移指令用于实现goto 功能;③长距离的转移指令用于子程序调用。
Thumb 指令集对每种情况采用不同的指令模式,分别如图4.4 所示。 前两种转移格式是条件域和偏移长度的折中。 第一种指令格式中条件域与ARM 指令相同。 前两种指令格式的偏移值都左移一位,以实现半字对齐,并符号扩展到32 位。 第三种指令格式中,Thumb 采用两条这样指令格式的指令组合成22 位半字偏移并符号扩展为32 位,使指令转移范围为±4 MB。 这是因为转移链接子程序通常需要一个大的范围,很难用16 位指令格式实现。 为了使这两条转移指令相互独立,使它们之间也能响应中断等,所以将链接寄存器LR 作为暂存器使用。 LR 在这两条指令执行完成后会被覆盖,因而LR 中不能装有效内容。 这个指令对的操作为:
图4.3 Thumb 指令二进制编码
(H=0) LR:=PC+(偏移量左移12 后符号扩展至32 位);
(H=1) PC:=LR+(偏移量左移1 位);LR :=oldPC + 3。
这里,oldPC 是第二条指令的地址;加3 使产生的地址指向下一条指令并且使最低位置位以指示这是一个Thumb 程序。 用3a 指令格式的指令代替上面的第二步,就可以实现BLX 指令。 指令格式3a 只在v5T 结构中有效。 它使用与上面的BL 指令同样的第一步:
(BL,H=0) LR:=PC+(偏移量左移12 后符号扩展至32 位);
(BLX) PC:=LR +(偏移量左移1 位)&0xffff_fffc;LR: =oldPC +3,清Thumb 指示位。
应注意该形式的指令转移的目标是ARM 指令,偏移地址只需要10 位而且必须对PC 值的位“1”(PC[1])进行清零操作。 第四种指令格式直接对应ARM 指令B{L}X,不同之处是BLX(仅在v5T 结构中有效)指令中r14 值为后续指令地址加“1”,以指示是被Thumb 代码调用。 指令中“H”置“1”时,选择高8 个寄存器(r8 ~r15)。
指令格式:
转移链接产生两条指令格式3 指令。 指令格式3 指令必须成对出现而不能单独使用。同样BLX 产生一条指令格式3 指令和一条指令格式3a 指令。 汇编器根据当前指令地址、目标指令标识符的地址以及对流水线行为的微调计算出应插入指令中相应的偏移量。 若转移目标不在寻址范围内,则给出错误信息。
下面分类详细介绍每一种转移指令。
(1)B
分支指令。 这是Thumb 指令集中唯一可以条件执行的指令。
①指令格式
其中:label 是程序相对偏移表达式,通常是在同一代码块内的标号。 若使用cond,则label必须在当前指令的-256 ~+256 字节范围内;若指令是无条件的,则label 必须在±2 KB 范围内。
②用法
若cond 满足或不使用cond,则B 指令引起处理器转移到label,label 必须在指定范围内。ARM 链接器不能增加代码来产生更长的转移。
③举例
(2)BL
带链接的长分支。
①指令格式
其中:label 为程序相对转移表达式。(www.xing528.com)
②用法
BL 指令将下一条指令的地址拷贝到R14(LR,链接寄存器),并引起处理器转移到label。BL 指令不能转移到当前指令±4 MB 以外的地址。 必要时,ARM 链接器插入代码以允许更长的转移。
③举例
(3)BX
分支指令,并可选择地切换指令集。
①指令格式
其中:Rm 装有分支目的地址的ARM 寄存器,Rm 的位[0]不用于地址部分。 若Rm 的位[0]清零,则位[1]也必须清零(因为在ARM 状态下,地址是字对齐的,所以最后两位必须为00);指令清除CPSR 中的标志T,目的地址的代码被解释为ARM 代码。
②用法
BX 指令引起处理器转移到Rm 存储的地址。 若Rm 的位[0]置位,则指令集切换到Thumb 状态。 若Rm 的位[0]置“0”,则指令集切换到ARM 状态。
③举例
(4)BLX
带链接分支,并可选地交换指令集。
①指令格式
其中:Rm 装有分支目的地址的ARM 寄存器。 Rm 的位[0]不用于地址部分。 若Rm 的位[0]清零,则位[1]也必须清零;指令清除CPSR 中的标志T,目的地址的代码被解释为ARM代码。 Label 是程序相对偏移表达式。 “BLX label”始终引起处理器切换到ARM 状态。
②用法
BLX 指令可用于:
a.拷贝下一条指令的地址到R14;
b.引起处理器转移到label 或Rm 存储的地址;
c.如果Rm 的位[0]清零,或使用“BLX label”形式,则指令集切换到ARM 状态。
③举例
指令不能转移到当前指令±4 MB 范围以外的地址,必要时,ARM 链接器插入代码(veneer)以允许更长的转移。 这条代码的作用就是使Thumb 采用两条BLX 指令组合成22 位的半字偏移,最终使指令转移范围为±4 MB。
注意,BLX 指令只有v5T 结构的ARM 微处理器支持。
在ARM 和Thumb 状态下,通常用BL 指令来调用子程序。 在不同的情况下有不同的返回方法,如下所述:
如果子程序由相同的指令集调用,则它可以用传统的BL 调用,用“MOV pc,r14”或“LDMFD sp!,{…,pc}”(在Thumb 代码中为POP“{…,pc}”)返回。 如果子程序由不相同的指令集调用,则可以用“BX lr”或“LDMFD sp!,{…,rN};BX rN”(在Thumb 代码中为“POP{…,rN};BX rN”)返回。 支持v5T 结构的ARM 微处理器也可以用LDMFD sp!,{…,pc}(在Thumb 代码中为POP {…,pc})返回,因为这些指令采用装载的PC 值的最低位来更新Thumb标志位。 早于v5T 结构的微处理器不支持这样的用法。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。