Thumb指令集之: ARM和Thumb的混合编程
在实现ARM代码和Thumb代码转换时,大部分的ARM指令有等价的Thumb指令,只有少数指令没有。如加载字节指令(LDR)不支持自动变址,软中断指令不能条件执行。
在编写Thumb代码时要注意以下几点。
①汇编器需要知道什么时候产生ARM代码、什么时候产生Thumb代码,程序中使用CODE32和CODE16伪操作提供给编译器这些信息。
②由于处理器上电执行是在ARM状态下完成的,所以要使用Thumb指令必须由ARM指令调用Thumb指令,这一过程是通过“BXLR”指令来实现的。需要注意的是,在使用“BXLR”指令前,要对寄存器LR做正确的初始化。
③在ARM和Thumb混合编程时,常使用ALIGN伪操作保证内存地址对齐。
11.10.2互交子程序
编写ARM/Thumb互交代码时,下面两点需要注意。
①对于C/C++子程序而言,只要在编译时指定--apcs/interwork选项,汇编器会生成合适的返回代码,使得程序返回到和调用程序相同的状态。
②在汇编语言子程序中,用户必须自己编写相应的返回代码,使得程序返回到和调用程序相同的状态。
如果目标代码包含以下内容,应该在编译或汇编时使用--apcs/interwork选项使处理器能够在ARM和Thumb代码间进行正确的切换,这种情况包含以下4种。
①需要返回到ARM状态的Thumb子程序。
②需要返回到Thumb状态的ARM子程序。
③间接调用ARM子程序的Thumb子程序。
④间接调用Thumb子程序的ARM子程序。
如果在程序连接阶段,连接器发现ARM子程序和Thumb子程序间存在相互调用,而源文件在编译时没有使用--apcs/interwork选项,则连接器将报告以下错误。
Error:L6239E:CannotcallARMsymbol'arm_function'innon-interworkingobject
armsub.ofromTHUMBcodeinthumbmain.o(.text)
其中,“arm_function”为需要进行状态切换的子程序名。
在这种情况下,用户必须使用--apcs/interwork选项重新对源文件进行编译。
但在下面两种情况下,不必指定--apcs/interwork选项。
①在Thumb状态下,发生异常中断时,处理器自动切换到ARM状态,这时不需要添加状态切换代码。
②当异常发生在Thumb状态时,从异常返回不需要添加状态切换的Veneer代码。
1.使用汇编语言实现互交
对于汇编程序来说,可以有两种方法来实现程序状态的切换。第一种方法是利用连接器提供的交互子程序Veneer来实现程序状态的切换,这时用户可以使用指令BL来调用子程序;另一种方法是用户自己编写状态切换的程序。
在ARMv4版本及其以前的版本中,可以使用BX指令实现程序状态的切换。
从ARMv5版本开始,下面的指令也可以用来实现程序的状态切换。
·BX(BranchandeXchange)
·BLX、LDR、LDM和POP
下面的两个伪操作用来区分源程序中的ARM代码和Thumb代码。
·CODE16
·CODE32
下面简单介绍用于状态切换的指令和伪操作,更详细的信息请分别参见相关章节。
(1)BX指令
ARM状态下的BX指令,使程序跳转到指令中指定的参数Rm指定的地址执行程序,Rm的第0位拷贝到CPSR中T位,位[31∶1]移入PC。若Rm的bit[0]为1,则跳转时自动将CPSR中的标志位T置位,即把目标地址的代码解释为Thumb代码;若Rm的位bit[0]为0,则跳转时自动将CPSR中的标志位T复位,即把目标地址代码解释为ARM代码。指令的语法格式如下。
BX{cond>}Rm>
①cond>
为指令编码中的条件域。它指示指令在什么条件下执行。当cond>忽略时,指令为无条件执行(cond=AL(Alway))。
②Rm>
包含跳转指令的目标地址。如果Rm的bit[0]=0,目标地址处指令为ARM指令;如果Rm的bit[0]=1,目标地址处指令为Thumb指令。
指令操作的伪代码。
指令操作的伪代码如下面程序段所示。
IfconditionPassed{cond}then
TFlag=Rm[0]
PC=RmAND0xfffffffe
Thumb状态下的BX指令,用于ARM和Thumb代码间的相互调用。
指令的语法格式。
BXRm>
其中Rm>为目标地址寄存器,包含程序的跳转地址。BX指令的目标地址寄存器可以是r0~r15中的任意寄存器。
注意 | 如果Rm[1:0]=0b10,不满足ARM指令的内存对齐方式。指令的执行结果不可预知。如果该指令使用r15作为目标寄存器,其操作方式和使用其他寄存器相同。 |
c++相关文章:c++教程
评论