新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 混合使用C、C++和汇编语之:内联汇编和嵌入型汇编的使用

混合使用C、C++和汇编语之:内联汇编和嵌入型汇编的使用

作者:时间:2013-09-30来源:网络收藏

本文引用地址:http://www.eepw.com.cn/article/257034.htm

3.嵌入式汇编程序表达式和++表达式之间的差异

嵌入式汇编表达式和表达式之间存在以下差异。

①汇编程序表达式总是无符号的。相同的表达式在汇编程序和C或中有不同值。例如:

MOVr0,#(-33554432/2)//结果为0x7f000000

MOVr0,#__cpp(-33554432/2)//结果为0xff000000

②以0开头的汇编程序编码仍是十进制的。例如:

MOVr0,#0700//十进制700

MOVr0,#__cpp(0700)//八进制0700等于十进制448

③汇编程序运算符优先顺序与C和不同。例如:

MOVr0,#(0x23:AND:0xf+1)//((0x230xf)+1)=>4

MOVr0,#__cpp(0x230xf+1)//(0x23(0xf+1))=>0

④汇编程序字符串不是以空字符为终止标志的:

DCBnotrailingnull//16bytes

DCB__cpp(Ihaveatrailingnull!!)//25bytes

注意

在_cpp标识符作用范围之内使用C或C++语法规则。

4.嵌入式汇编函数的生成

由关键字__asm声明的嵌入式汇编程序,在编译时将作为整个文件体传递给汇编器。传递过程中,__asm函数的顺序保持不变(用模板实例生成的函数除外)。正是由于嵌入式汇编的这个特性,使得由一个__asm标识的嵌入式汇编程序调用在同一文件中的另一个嵌入式汇编程序是可以实现的。

当使用编译器armcc时,局部链接器(PartialLink)将汇编程序产生的目标文件与编译C程序的目标文件相结合,产生单个目标文件。

编译程序为每个__asm函数生成AREA命令。例如,以下__asm函数:

#includecstddef>

structX{intx,y;voidaddto_y(int);};

__asmvoidX::addto_y(int){

LDRr2,[r0,#__cpp(offsetof(X,y))]

ADDr1,r2,r1

STRr1,[r0,#__cpp(offsetof(X,y))]

BXlr

}

对于此函数,编译程序生成:

AREA||.emb_text||,CODE,READONLY

EXPORT|_ZN1X7addto_yEi|

#linenumfile

|_ZN1X7addto_yEi|PROC

LDRr2,[r0,#4]

ADDr1,r2,r1

STRr1,[r0,#4]

BXlr

ENDP

END

由上面的例子可以看出,对于变量offsetof的使用必须加__cpp()标识符才能引用,因为该变量是在cstddef头文件中定义的。

由__asm声明的常规函数被放在名为.emb_text的段(Section)中。这一点也是嵌入式汇编和最大的不同。相反,隐式实例模板函数(ImplicitlyInstantiatedTemplateFunction)和函数放在与函数名同名的区域(Area)内,并为该区域增加公共属性。这就确保了这类函数的特殊语义得以保持。

由于内联和模板函数的区域的特殊命名,所以这些函数不按照文件中定义的顺序排列,而是任意排序。因此,不能以__asm函数在原文件中的排列顺序,来判断它们的执行顺序,也就是说,即使两个连续排列的__asm函数,也不一定能顺序执行。

5.关键字__cpp

可用__cpp关键字从汇编代码中访问C或C++的编译时常量表达式,其中包括含有外部链接的数据或函数地址。标识符__cpp内的表达式必须是适合用作C++静态初始化的常量表达式(请参阅ISO/IEC14882:1998中的3.6.2非本地对象初始化一节和本书的常量表达式一节)。

编译时,编译器将使用__cpp(expr)的地方用汇编程序可以使用的常量所取代。例如:

LDRr0,=__cpp(some_variable)

LDRr1,=__cpp(some_function)

BL__cpp(some_function)

MOVr0,#__cpp(some_constant_expr)

__cpp表达式中的名称可在__asm函数的C++上下文中查阅。__cpp表达式结果中的任何名称按照要求被损毁并自动为其生成IMPORT语句。

6.手动重复解决方案

可以在嵌入式汇编中使用C++转换为非虚拟函数调用解决重复。例如:

voidg(int);

voidg(long);

structT{

intmf(int);

intmf(int,int);

};

__asmvoidf(T*,int,int){

BL__cpp(static_castint(T::*)(int,int)>(T::mf))//callsT::mf(int,int)

BL__cpp(static_castvoid(*)(int)>(g))//callsg(int)

MOVpc,lr

}

c语言相关文章:c语言教程


c++相关文章:c++教程




评论


相关推荐

技术专区

关闭