我有以下代码可以在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], %r0\n\t"
"mov %[__run], %r5\n\t"
"mov %[__stack], %%sp\n\t"
"blx %r5\n\t"
: /* no output operands */
: [__stack] "r" (_stack),
[__this] "r" (_this),
[__run] "r" (_run)
: /* no clobbers */);
问:在x86 asm中,使用thiscall调用约定,“this”指针进入ecx。 它在哪里?
修改
修改
我正在尝试做的全部实现是: http://pastebin.com/6mrUC7td
它在visual studio中完美运行,但我无法让它在XCode / iOS中正常工作
答案 0 :(得分:3)
arm abi指定寄存器r0
到r3
用于参数传递。 this
指针始终位于第一个寄存器中,这将是r0
。
答案 1 :(得分:2)
对于来自gcc内联汇编程序的call
任何东西都不是特别安全,因为没有办法告诉编译器它(没有约束到gcc内联asm指令可以表达“这个东西包含函数调用,执行所有必要的操作来保存/恢复保存在寄存器中的任何内容,这些寄存器在进行函数调用时可能会发生变化“。
理论上你可以通过给出一个clobber列表来“手动”执行该操作,该列表指定在根据平台ABI进行函数调用时可能更改的所有寄存器(在ARM上相当多,我认为它是几乎所有这些都不包括sp
...)。但是这样做经常会导致gcc告诉你无法满足约束的情况(即它没有留下任何寄存器来填充“需要保留的东西”),具体取决于使用内联asm的上下文。 / p>
为什么需要从内联汇编中调用函数?您是否可以使用static inline
函数将普通C代码(执行函数调用)与内联汇编相结合,以执行只能在内联汇编中执行的操作?
如果整个函数仅为内联汇编,则ARM上的gcc提供了一种出路 - 即__attribute__((naked))
选项。这告诉编译器不要为它创建函数序言/结尾,并且你有义务自己编写这些函数,即添加保存/恢复此函数使用但由EABI保存的寄存器的代码。通过将函数调用的内联汇编“外包”到static inline __attribute__((naked))
函数中,您可以不得不指定大量的clobber列表,因为编译器会识别它是一个函数调用(并根据需要保留/恢复它,即使在内联代码时也是如此。
答案 2 :(得分:0)
看看this。虽然它使用x86组件,但同样适用于臂组件。
答案 3 :(得分:0)
我不太确定你在那里使用堆栈指针做什么 - 这是你在ARM上不需要的x86成语还是你故意尝试设置一个新的堆栈指针?
在任何情况下,堆栈指针都在r13
中 - 程序计数器为r15
- LDR
或MOV
进入PC
会影响分支。在函数序言之外,SP已经指向堆栈上的下一个位置,因此如果由于寄存器r0-r3
不够而需要在堆栈上传递参数,则只需要修改它 - 这是不是这里的情况。
如果你确实修改了堆栈指针,你需要在函数调用后恢复它,否则你退出函数时会有一个很小的崩溃。
最后,您需要声明ARM [E] ABI允许被调用者在函数调用时修改为所有寄存器的寄存器。这是r0-r3
,r9
{可能}和r12
。
如果您在iOS上这样做,ISTR会对寄存器的使用情况产生微妙的变化。
答案 4 :(得分:0)
获得ABI所需信息的简单解决方案(比如哪些寄存器获得了传递的值):只需编写几行虚拟代码,调用c ++方法,然后反汇编结果(在目标平台上)。 / p>