混合使用C、C++和汇编语之:内联汇编和嵌入型汇编的使用
10.嵌入式汇编版本间的差异
不同版本的ARM编译器对嵌入式汇编程序的语法要求会有所差异。在具体使用时请参见相关文档。
值得注意的是,目前的嵌入式汇编器已经完全支持ARMv6指令集,也就是说可以在嵌入式汇编中使用ARMv6指令集中的指令。
12.1.3内联汇编中使用SP、LR和PC寄存器的遗留问题
虽然目前的编译器不支持在内联汇编中使用SP、LR和PC寄存器,但在RVCTv1.2及其以前的编译器版本中是允许的。下面的例子显示了使用早期编译器版本,在内联汇编中使用LR寄存器的例子。
voidfunc()
{
intvar;
__asm
{
movvar,lr/*得到func()函数的返回地址*/
}
}
如果使用RVCTv2.0编译器编译上面的代码,编译器将报告以下错误。
Error:#20:identifierlrisundefined
使用RVCTv2.0版本及其以后的编译器,要在C或C++代码中使用汇编访问SP、LR和PC寄存器可以使用下面几种方法。
①使用嵌入式汇编代码。嵌入式汇编支持所有的ARM指令,同时允许在代码中访问SP、LR和PC寄存器。
②在内联汇编中使用以下一些指令。
·__current_pc():访问PC寄存器。
·__current_sp():访问SP寄存器。
·__return_address():访问LR,返回地址寄存器。
下面给出了两个访问SP、LR和PC寄存器的典型实例程序。
①使用编译器给定的指令。
voidprintReg()
{
unsignedintspReg,lrReg,pcReg;
__asm{
MOVspReg,__current_sp()
MOVpcReg,__current_pc()
MOVlrReg,__return_address()
}
printf(SP=0x%Xn,spReg);
printf(PC=0x%Xn,pcReg);
printf(LR=0x%Xn,lrReg);
}
②使用嵌入式汇编。
__asmvoidfunc()
{
MOVr0,lr
...
BXlr
}
使用嵌入式汇编可以使用调试器捕获程序的返回地址。
12.1.4内联汇编代码与嵌入式汇编代码之间的差异
本节总结了内联汇编和嵌入式汇编在编译方法上存在的差异:
·内联汇编代码使用高级处理器抽象,并在代码生成过程中与C和C++代码集成。因此,编译程序将C和C++代码与汇编代码一起进行优化。
·与内联汇编代码不同,嵌入式汇编代码从C和C++代码中分离出来单独进行汇编,产生与C和C++源代码编译对象相结合的编译对象。
·可通过编译程序来内联内联汇编代码,但无论是显式还是隐式,都无法内联嵌入式汇编代码。
表12.1总结了内联汇编程序与嵌入式汇编程序之间的主要差异。
表12.1 内联汇编程序与嵌入式汇编程序之间的主要差异
功能 | 嵌入式汇编程序 | 内联汇编程序 |
指令集 | ARM和Thumb | 仅支持ARM |
ARM汇编指令伪操作 | 支持 | 不支持 |
ARMv6指令集 | 支持 | 仅支持媒体指令 |
C/C++表达式 | 只支持常数表达式 | 完全支持 |
汇编代码是否优化 | 无优化 | 完全优化 |
能否被内联(Inling) | 不可能 | 有可能被内联 |
续表
功能 | 嵌入式汇编程序 | 内联汇编程序 |
寄存器访问 | 使用指定的物理寄存器,还可以使用PC、LR和SP | 使用虚拟寄存器。不能使用PC、LR和SP寄存器 |
是否自动产生返回指令 | 手工添加返回指令 | 指定产生(但不支持BX、BXJ和BLX指令) |
是否支持BKPT指令 | 不直接支持 | 不支持 |
c语言相关文章:c语言教程
c++相关文章:c++教程
评论