Thumb指令集之: ARM和Thumb的混合编程
SWI 0x123456 ;ARM semihosting SWI软中断调用
END ;文件结束
上面的例子分为4部分,通过下面的步骤编译和运行。
① 使用文本编辑器,如notepad,输入上面的代码,并保存成文件addreg.s;
② 在命令行中键入汇编命令 armasm –g addreg.s;
③ 在命令行中键入链接命令 armlink addreg.o -o addreg;
④ 使用调试器(Debugger)(如,RealView Debuggeror AXD)运行映像文件。可以使用单步执行,观察代码在Thumb状态下的执行。
| 注意 | Thumb代码的地址标号如果用伪操作export声明为"外部的",则连接器会自动调整该地址标号使其bit[0]等于1;如果该地址标号没有被声明为"外部的",则使用者必须手动地对标号进行调整,如上例中的ThumProg+1。 |
(5)ARMv5架构下的状态切换
在ARMv5体系结构的指令集中,增加了下面两条指令用于ARM和Thumb代码互交。
· BLX address
该指令跳转到指令中指定的地址处执行程序并进行程序状态切换,该地址是"PC相关的",地址范围为±32MB(ARM状态)或±4MB(Thumb状态)。
· BLX register
在该中格式的跳转指令中寄存器Rm指定转移目标,Rm的第0位拷贝到CPSR中的T位,bit[31:0]移入PC。
使用上面两条指令,在执行程序跳转之前,处理器自动将返回连接寄存器LR的bit[0]位更新为CPSR寄存器的T位,所以无论处理器状态是否发生变化,程序都能正确返回。
当使用LDR、LDM及POP指令向PC寄存器中赋值时,寄存器CPSR中的Thumb位将被设置成PC寄存器的bit[0],这时就实现了程序状态的切换。这种方法在子程序的返回时非常有效,同样的指令可以根据需要返回到ARM状态或Thumb状态。
连接器在对目标代码进行连续时,将代码中的地址标号分为3类。
· ARM指令地址标号。
· Thumb指令地址标号。
· 数据(Data)地址标号。
当连接器重定位Thumb代码中的地址标号时,地址标号的bit[0]位将被自动设置为1。这就意味着跳转指令(这些指令包括BX、BLX和LDR)可以根据目标地址正确的进行状态切换。
| 注意 | 上面提到的连接器自动设置目的地址的行为,只有在ARMv5及其以上版本中支持。 |
2.使用C和C++语言实现互交
对于不同的C和C++源程序,可以有些程序中包含ARM指令,有些程序中包含Thumb指令,这些程序可以相互调用,只是在编译这些程序时指定--apcs/interwork选项。当使用了--apcs/interwork选项,编译器会自动进行一些相应处理;连接器在检测到程序中存在互交工作时,会生成一些用于程序状态切换的代码。
(1)代码编译
可以使用下面的指令,将C或C++程序编译为可以执行互交的目标代码。
armcc --c90 --thumb --apcs /interwork
armcc --c90 --arm --apcs /interwork
armcc --cpp --thumb --apcs /interwork
armcc --cpp --arm --apcs /interwork
| 注意 | --cpp是C++文件(文件后缀为.cpp)默认的编译选项。 |
使用--apcs/interwork选项对文件进行编译时,编译器会进行如下处理。
· 对于叶子程序(leaf function,即程序中没有其他子程序调用的程序),编译器将程序中的"MOV PC,LR"指令替换成"BX LR"指令,因为"MOV PC"指令不能进行状态切换。
· 对于非叶子程序,要进行一系列的指令替换,如:
POP {r4,r5,pc}
替换为:
POP {r4,r5}
POP {r3}
BX r3
下面的例子显示了一段带子程序调用的C语言程序,使用--apcs/interwork选项进行编译时,对代码产生的影响。
C语言源程序。
Void func(void)
{
….
Sub()
..
}
使用armcc --apcs/interwork选项进行编译产生结果如下。
Func
STMFD sp!,{r4-r7,lr}
….
BL sub
….
LDMFD sp!, {r4-r7,lr}
BX lr
使用tcc --apcs/interwork选项进行编译产生结果如下。
PUSH {r4-r7,lr}
….
BL sub
….
POP {r4-r7}
POP {r3}
BX
(2)C语言的互交实例
下面的例子显示了一个Thumb状态下的代码通过互交调用ARM子程序;而后又在ARM子程序中调用Thumb指令集的库函数printf()。
/*********************
* thumbmain.c *
**********************/
#include <stdio.h>
extern void arm_function(void);
int main(void)
{
printf("Hello from Thumb World\n");
Thumb指令集 ARM 混合编程 Veneer AAPCS 相关文章:
- Thumb指令集之: Thumb指令的特点及实现(08-30)
- Thumb指令集之: Thumb跳转指令(08-30)
- Thumb指令集之: Thumb指令应用(08-30)
- Thumb指令集与ARM指令集的区别(11-21)
- Thumb指令集之: Thumb指令应用(09-30)
- Thumb指令集之: 多寄存器数据传送指令(09-30)