如何从gcc内联arm7程序集中调用c++成员函数
How to call a c++ member function from gcc inline arm7 assembly
我有以下一段在x86上工作的代码,我需要将其转换为gcc/arm7内联程序集。
替换堆栈似乎很简单,只需将堆栈指针移动到r15
而不是esp
,但我不知道如何调用该函数,或将实际变量放入arm汇编代码中。
Object *c;
unsigned long _stack = (unsigned long)c->stack + 65535;
void (Object::*_run)() = &Object::_run;
__asm
{
mov ecx, _this // store pointer to this Object
mov edx, _run // store address of _run() function
mov esp, stack // replace stack pointer with Object's internal stack
call edx // call the _run() function
}
编辑:
到目前为止,我有这个:
unsigned long _stack = (unsigned long)c->stack + 65535;
void (Object::*_run)() = &Object::_run;
asm volatile("mov %[__this], %r0nt"
"mov %[__run], %r5nt"
"mov %[__stack], %%spnt"
"blx %r5nt"
: /* no output operands */
: [__stack] "r" (_stack),
[__this] "r" (_this),
[__run] "r" (_run)
: /* no clobbers */);
Q: 在x86 asm中,使用thiscall调用约定,"this"指针进入ecx。它的手臂在哪里?
编辑:
A: For C++, an implicit this parameter is passed as an extra argument that immediately precedes the first user argument. Other rules for marshalling C++ arguments are described in CPPABI.
编辑:
我想做的事情的全面实施如下:http://pastebin.com/6mrUC7td
它在visualstudio中运行得很好,但我无法使它在XCode/iOS 中正常运行
arm abi指定寄存器r0
到r3
用于参数传递。this
指针总是在第一个寄存器中,这将是r0
。
从gcc内联汇编程序中call
的任何东西都不是特别安全,因为没有办法告诉编译器这一点(gcc内联asm指令的约束可以表示"这件事包含一个函数调用,执行所有必要的操作来保存/恢复寄存器中的任何内容,这些内容在进行函数调用时可能会更改")。
理论上,你可以通过给出一个clobber列表来"手动"实现这一点,该列表指定在根据平台ABI进行函数调用时可能更改的所有寄存器(在ARM上有很多,我认为几乎所有寄存器都不包括sp
…)(即,它没有任何寄存器来填充"需要保存的东西"),这取决于使用内联asm的上下文。
为什么需要从内联程序集中调用函数?难道你不能用一个static inline
函数来代替它,它将普通的C代码(函数调用它)与内联汇编结合起来,来做只能在内联汇编中完成的事情吗?
如果整个函数仅为内联汇编,则ARM上的gcc提供了一种解决方案,即__attribute__((naked))
选项。这告诉编译器不要为其创建函数序言/结束语,您有义务自己编写这些,即添加保存/恢复此函数使用但由EABI声明保留的寄存器的代码。通过将执行函数调用的内联程序集"外包"到static inline __attribute__((naked))
函数中,您可以避免指定大量的clobber列表,因为编译器会识别出这是一个函数调用(并根据需要保留/恢复它,即使在内联代码时也是如此)。
看看这个。尽管它使用x86程序集,但同样适用于arm程序集。
我不太确定你在用堆栈指针做什么——这是ARM上不需要的x86习惯用法,还是你有意设置一个新的堆栈指针?
在任何情况下,堆栈指针都在r13
中-程序计数器是r15
-LDR
或MOV
到PC
中会影响分支。在函数prolog之外,SP已经指向堆栈上的下一个位置,因此只有当由于寄存器r0-r3
不够而需要在堆栈上传递参数时,才需要修改它——这里的情况并非如此。
若您确实修改了堆栈指针,您需要在函数调用后恢复它,否则在函数退出时会出现一个很好的小崩溃。
最后,您需要将ARM[E]ABI允许被调用者在函数调用时修改的所有寄存器声明为clobbered。这是r0-r3
、r9
{可能}和r12
。
如果你在iOS上这样做,ISTR在注册使用方面会有细微的变化。
获取ABI所需信息的简单解决方案(比如在哪些寄存器中获取传递的值):只需在调用c++方法的地方写几行伪代码,然后反汇编结果(在目标平台上)。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- 在内联程序集中定义函数和从 C++ 调用时出现问题
- 如何在内联程序集中调用函数时保留堆栈
- 从重载集中调用具有特定函数的函子
- 如何从gcc内联arm7程序集中调用c++成员函数
- 从程序集中调用的C++方法返回对象数据
- 使用结构参数从程序集中调用C++函数
- 我是否应该将所有对new/delete的调用集中到一个类
- 在一个程序集中从本机调用c#
- 在新托管线程中通过 C# 在混合模式程序集中调用 STL 矢量的push_back