淮安市城市建设档案馆网站,网站及app开发,深圳华强北招聘网,什么是专业建设12.4C target_blank stylecursor:pointer;color:#D05C38;text-decoration:underline;C、C和ARM汇编语言之间的调用本节提供一些示例#xff0c;显示如何从C调用C和汇编语言代码#xff0c;以及从C和汇编语言调用C代码。其中包括调用约定和数据类型。主要包括下面内容 target_blank stylecursor:pointer;color:#D05C38;text-decoration:underline;C、C和ARM汇编语言之间的调用本节提供一些示例显示如何从C调用C和汇编语言代码以及从C和汇编语言调用C代码。其中包括调用约定和数据类型。主要包括下面内容·相互调用的一般规则·C语言的特定信息·调用示例。只要遵循正确的过程调用标准AAPCS就可以混合调用C、C和汇编语言例程。有关AAPCS的更多信息请参阅ARM相关文档。12.4.1相互调用的一般规则以下一般规则适用于C、C和汇编语言之间的调用。有关的详细信息请参阅ARM开发相关文档。嵌入式汇编程序以及其与ARM嵌入式应用程序二进制接口(BSABIApplicationBinaryInterfacefortheARMArchitecture)的兼容使得混合语言编程更易于实现。它们可提供以下功能·使用__cpp关键字进行名称延伸·传递隐含this参数的方式·调用虚函数的方式·引用的表示·具有基类或虚成员函数的C类的类型布局·非POD(PlainOldData)结构的类对象传递。以下一般规则适用于混合语言编程·使用C调用约定。·在C中非成员函数可以声明为externC以指定它们有C链接。带有C链接意味着定义函数的符号未延伸。C链接可以用于以一种语言实现函数然后用另一种语言调用它。·汇编语言模块所必须符合的AAPCS调用标准应当适合于应用程序所使用的存储器模型。以下规则适用于从C和汇编语言调用C函数·要调用全局(非成员)C函数应将它声明为externC以提供C链接。·成员函数(静态和非静态)总是有已延伸的名称。使用嵌入式汇编程序的__cpp关键字可以不必手工寻找已延伸的名称。·不能从C调用C内联函数除非确保C编译器生成了函数的外联副本。例如取得函数地址将导致生成外联副本。·非静态成员函数接受隐含this参数作为r0中的第一个自变量或作为r1中第二个自变量(如果函数返回非int类结构)。静态成员函数不接受隐含this参数。12.4.2C的特定信息本节主要介绍一些专门适用于C的内容。(1)C调用约定ARMC使用与ARMC相同的调用约定但在下面的情况下调用规则有所不同·调用非静态成员函数时隐含的this参数是第一个自变量或者是第二个自变量(如果被调用函数返回非int类的struct)。这可能在将来的版本中有所变化。(2)C数据类型ARMC使用与ARMC相同的数据类型但在以下几种情况下情况有所不同·如果struct或class类型的C对象没有基类或虚函数则它们的布局与ARMC相同。如果这样的struct没有用户定义的复制赋值运算符或用户定义的析构函数则它是POD结构。·引用表示为指针。·C函数指针和C(非成员)函数指针没有区别。(3)符号名称延伸链接程序将取消信息中符号名称的延伸。在C程序中C名称必须声明为externC。ARMISOC头文件已经完成此操作。详细信息请参阅ARM相关文档。12.4.3混合编程调用举例汇编程序、C程序以及C程序相互调用时要特别注意遵守相应的AAPCS。下面一些例子具体说明了在这些混合调用中应注意遵守的AAPCS规则。这些示例程序默认为使用非软件栈检查的ATPCS规则因为它们执行栈操作时不检查栈溢出。(1)从C调用汇编语言下面的程序显示如何在C程序中调用汇编语言子程序该段代码实现了将一个字符串复制到另一个字符串。#includeexternvoidstrcopy(char*d,constchar*s);intmain(){constchar*srcstrFirststring-source;chardststr[]Secondstring-destination;/*下面将dststr作为数组进行操作*/printf(Beforecopying:\n);printf(%s\n%s\n,srcstr,dststr);strcopy(dststr,srcstr);printf(Aftercopying:\n);printf(%s\n%s\n,srcstr,dststr);return(0);}下面为调用的汇编程序。PRESERVE8AREASCopy,CODE,READONLYEXPORTstrcopyStrcopy ;r0指向目的字符串;r1指向源字符串LDRBr2,[r1],#1 ;加载字节并更新源字符串指针地址STRBr2,[r0],#1 ;存储字节并更新目的字符串指针地址CMPr2,#0 ;判断是否为字符串结尾BNEstrcopy ;如果不是程序跳转到strcopy继续拷贝MOVpc,lr ;程序返回END按以下步骤从命令行编译该示例①输入armasm-gscopy.s编译汇编语言源代码。②输入armcc-c-gstrtest.c编译C源代码。③输入armlinkstrtest.oscopy.o-ostrtest链接目标文件。④将ELF/DWARF2兼容调试器与相应调试目标配合使用运行映像。(2)汇编语言调用C程序下面的例子显示了如何从汇编语言调用C程序。下面的子程序段定义了C语言函数。intg(inta,intb,intc,intd,inte){returnabcde;}下面的程序段显示了汇编语言调用。假设程序进入f时r0中的值为i。;intf(inti){returng(i,2*i,3*i,4*i,5*i);}PRESERVE8EXPORTfAREAf,CODE,READONLYIMPORTg //声明C程序g()STRlr,[sp,#-4]! //保存返回地址lrADDr1,r0,r0 //计算2*i(第2个参数)ADDr2,r1,r0 //计算3*i(第3个参数)ADDr3,r1,r2 //计算5*iSTRr3,[sp,#-4]! //第五个参数通过堆栈传递ADDr3,r1,r1 //计算4*i(第4个参数)BLg //调用C程序ADDsp,sp,#4 //从堆栈中删除第5个参数LDRpc,[sp],#4 //返回END(3)从C调用C下面的例子显示了如何从C程序中调用C函数。下面的C程序调用了C程序。structS{ //本结构没有基类和虚函数S(ints):i(s){}inti;};externCvoidcfunc(S*);//被调用的C函数使用extern“C”声明intf(){Ss(2); //初始化scfunc(s); //调用C函数cfunc将改变sreturnsi*3;}下面显示了被调用的C程序代码。structS{inti;};voidcfunc(structS*p){/*定义被调用的C功能*/p-i5;}(4)从C中调用汇编下面的例子显示了如何从C中调用汇编程序。下面的例子为调用汇编程序的C代码。structS{ //本结果没有基类和虚拟函数//S(ints):i(s){}inti;};externCvoidasmfunc(S*); //声明被调用的汇编函数intf(){Ss(2); //初始化结构体sasmfunc(s); //调用汇编子程序asmfuncreturns.i*3;}下面是被调用的汇编程序。PRESERVE8AREAAsm,CODEEXPORTasmfuncasmfunc//被调用的汇编程序定义LDRr1,[r0]ADDr1,r1,#5STRr1,[r0]MOVpc,lrEND(5)从C中调用C下面的例子显示了如何从C代码中调用C程序。下面的代码显示了被调用C代码。structS{//本结构没有基类和虚拟函数S(ints):i(s){}inti;};externCvoidcppfunc(S*p){//定义被调用的C代码//连接了C功能p-i5;//}调用了C代码的C函数。structS{inti;};externvoidcppfunc(structS*p);/*声明将会被调用的C功能*/intf(void){structSs;s.i2;/*初始化S*/cppfunc(s);/*调用cppfunc函数该函数可能改变S的值*/returns.i*3;}(6)从汇编中调用C程序下面的代码显示了如何从汇编中调用C程序。下面是被调用的C程序。structS{//本结构没有基类和虚拟函数S(ints):i(s){}inti;};externCvoidcppfunc(S*p){//定义被调用的C功能//功能函数体p-i5;}在汇编语言中声明要调用的C功能使用带连接的跳转指令调用C功能。AREAAsm,CODEIMPORTcppfunc ;声明被调用的C函数名EXPORTffSTMFDsp!,{lr}MOVr0,#2STRr0,[sp,#-4]! ;初始化结构体MOVr0,sp ;调用参数为指向结构体的指针BLcppfunc ;调用C功能cppfuncLDRr0,[sp],#4ADDr0,r0,r0,LSL#1LDMFDsp!,{pc}END(7)在C和C函数间传递参数下面的例子显示了如何在C和C函数间传递参数。下面的代码为C函数。externCintcfunc(constint);//声明被调用的C函数externCintcppfunc(constintr){//定义将被C调用的C函数return7*r;}intf(){inti3;returncfunc(i); //相C函数传参}下面为C函数。externintcppfunc(constint*);/*声明将被调用的C函数*/intcfunc(constint*p){/*定义被C调用的C函数*/intk*p4;returncppfunc(k);}(8)从C或汇编语言调用C下面的例子综合显示了如何从C或汇编语言中调用非静态、非虚的C成员函数。可以使用编译器编译出的汇编程序查找已延伸的函数名。下面是被调用的C成员函数。structT{T(inti):t(i){}intt;intf(inti);};intT::f(inti){returnit;}//定义将被C调用的C功能函数externCintcfunc(T*);//声明将被C调用的C函数intf(){Tt(5);//createanobjectoftypeTreturncfunc(t);}下面为调用C的C语言函数。structT;externint_ZN1T1fEi(structT*,int);/*被调用的C函数名*/intcfunc(structT*t){/*定义被C调用的C函数*/return3*_ZN1T1fEi(t,2);/*实现3乘以t-f(2)功能*/}下面为调用C的汇编函数。EXPORTcfuncAREAfoo,CODEIMPORT_ZN1T1fEicfuncSTMFDsp!,{lr} ;此时r0已经包含了指向对象的指针MOVr1,#2BL_ZN1T1fEiADDr0,r0,r0,LSL#1 ;r0乘以3LDMFDsp!,{pc}END下面的例子显示了如何用嵌入式汇编语言实现上面的例子。在此例中使用__cpp关键字引用该函数。因此用户不必了解已延伸的函数名。structT{T(inti):t(i){}intt;intf(inti);};intT::f(inti){returnit;}//定义被C调用的汇编功能__asmintasm_func(T*){STMFDsp!,{lr}MOVr1,#2;BL__cpp(T::f);ADDr0,r0,r0,LSL#1;r0乘以3LDMFDsp!,{pc}}intf(){Tt(5);//创建T类型的对象returnasm_func(t);}联系方