微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Thumb指令集之: ARM和Thumb的混合编程

Thumb指令集之: ARM和Thumb的混合编程

时间:08-30 来源:3721RD 点击:

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");

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top