混合使用C、C++和汇编语之:内联汇编和嵌入型汇编的使用
编中使用C++转换为非虚拟函数调用解决重复。例如:
void g(int);
void g(long);
struct T {
int mf(int);
int mf(int,int);
};
__asm void f(T*, int, int) {
BL __cpp(static_cast<int (T::*)(int, int)>(&T::mf)) // calls T::mf(int, int)
BL __cpp(static_cast<void (*)(int)>(g)) // calls g(int)
MOV pc, lr
}
7.相关基类的关键字
利用以下关键字可以确定从对象起始处到其相关基类的偏移量:
__offsetof_base(D, B)
其中,B必须是D的非虚拟基类。
该函数返回从D对象的起始处到其中B基子对象的起始处的偏移量。结果可能是零。必须将偏移量(以字节为单位)添加到D* p来执行。
static_cast<B*>(p) 的等效功能,如下程序段所示:
__asm B* my_static_base_cast(D* /*p*/) {
if __offsetof_base(D, B) <> 0 //排除偏移量为0的情况
ADD r0, r0, #__offsetof_base(D, B)
endif
MOV pc, lr
}
在汇编程序源代码中,这些关键字被转换为整数或逻辑常量。只能将它们用于__asm函数,而不能用于__cpp表达式。
8.成员函数类的关键字
以下关键字方便了从__asm函数中调用虚拟或非虚拟成员函数。以__mcall开头的关键字可用于虚拟和非虚拟函数。以__vcall开头的关键字仅能用于虚拟函数。在调用静态成员函数的过程中,这些关键字没有特别的作用。
下面详细介绍这些关键字的使用。
① __mcall_is_virtual(D, f)
如果f是D中的虚拟成员函数或是D的基类,结果是{TRUE},否则结果是{FALSE}。如果返回{TRUE},可用虚拟调度进行调用,否则必须直接进行调用。
② __mcall_is_in_vbase(D, f)
如果f是D虚拟基类中的非静态成员函数,结果是{TRUE},否则结果是{FALSE}。如果返回{TRUE},必须用__mcall_offsetof_vbaseptr(D, f)进行this调整,否则必须用__mcall_this_
offset(D, f)进行调整。
③ __mcall_this_offset(D, f)
其中D是类,f是D中定义的非静态成员函数或是D的非虚拟基类。该函数返回从D对象的起始处到定义f的基的起始处的偏移量。在用指向D的指针调用f的过程中,这是必要的this调整。返回值在D中可找到f时为零,或者与__offsetof_base(D, B)相同,其中B为包含f的D非虚拟基类。在D的虚拟基类中找到f时,如果使用__mcall_this_offset(D, f),则返回任意值,在程序中使用该返回值,汇编器将报告__mcall_this_offset无效使用的错误。
④ __vcall_offsetof_vfunc(D, f)
其中D是类,f是D中定义的虚拟函数或是D的基类。将偏移量返回到虚拟函数表,在该表中可以找到从虚拟函数表到虚拟函数的偏移量。在f不是虚拟成员函数时,如果使用__vcall_offsetof_vfunc(D, f),则返回任意值,而在设计上使用该值时会导致汇编错误。
9.调用非静态成员函数
本小节列出了可以从 __asm 函数中调用虚拟或非虚拟函数的关键字。静态成员函数的参数不相同(没有 this),使得检测静态成员函数的关键字__mcall_is_static不可用,因此调用位置很可能已经专用于调用静态成员函数。
(1)调用非虚拟成员函数
例如,在虚拟基(virtual base)或非虚拟基(non-virtual base)中,以下代码可用于调用虚拟函数:
// rp包含指向D的指针,该程序的功能是实现在使用rp时调用D的非虚成员函数f
// 所有参数准备好
// 假设并不返回一个结构类型
if __mcall_is_in_vbase(D, f)
ASSERT {FALSE} // can't access virtual base
else
MOV r0, rp //使用指向D的指针rp*
ADD r0, r0, #__mcall_this_offset(D, f) //地址调整
endif
BL __cpp(&D::f)
(2)调用虚拟成员函数
例如,在虚拟或非虚拟基中,以下代码可用于调用虚拟函数:
// rp包含指向D的指针,该程序的功能是在使用rp时调用D的虚拟函数f
// 所有参数准备好
// 假如函数并不返回一个结构类型
if __mcall_is_in_vbase(D, f)
ASSERT {FALSE} // 不能调用虚拟基
else
MOV r0, rp // 使用指向D的指针rp
LDR r12, [rp] // 加载vtable表结构指针
ADD r0, r0, #__mcall_this_offset(D, f) // 地址调整
endif
MOV lr, pc // 保存返回地址到lr
LDR pc, [r12, #__vcall_offsetof_vfunc(D, f)] // 调用函数rp→f()
10.嵌入式汇编版本间的差异
不同版本的ARM编译器对嵌入式汇编程序的语法要求会有所差异。在具体使用时请参见相关文档。
值得注意的是,目前的嵌入式汇编器已经完全支持ARMv6指令集,也就是说可以在嵌入式汇编中使用ARM
C C++ 汇编语言 ARM 内联汇编 嵌入型汇编 相关文章:
- RedHatLinux新手入门教程(5)(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- VXWORKS内核分析(11-11)
- 嵌入式开发工具简介(11-09)
- Linux2.4内核为我们带来了什么?(11-12)
- RedHatLinux新手入门教程(11-12)