0

我有以下适用于 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。它在哪里?

编辑:

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

它在视觉工作室中完美运行,但我无法让它在 XCode/iOS 中正常运行

4

5 回答 5

3

arm abi指定r0用于r3参数传递的寄存器。this指针总是在第一个寄存器中,这将是r0.

于 2012-08-05T09:58:45.413 回答
2

对于 gcc 内联汇编器中的任何东西都不是特别安全call,因为没有办法告诉编译器它(对 gcc 内联 asm 指令没有约束可以表示“这个东西包含一个函数调用,做所有必要的保存/恢复你保留的任何内容在进行函数调用时可能会更改的寄存器中”)。

理论上,您可以通过提供一个 clobber 列表来“手动”执行此操作,该列表指定在根据平台 ABI 进行函数调用时可能更改的所有寄存器(在 ARM 上很多,我认为几乎所有这些寄存器都不包括sp......) . 但是这样做经常会导致 gcc 告诉您无法满足约束的情况(即它没有任何寄存器可以将“需要保留的东西”填充到其中),具体取决于使用内联汇编的上下文。

为什么你需要从内联程序集中调用一个函数?难道你不能使用一个static inline函数来代替普通的 C 代码(它执行函数调用)和内联汇编来完成只能在内联汇编中完成的事情吗?

如果整个函数只是内联汇编,ARM 上的 gcc 提供了一个出路——即__attribute__((naked))选项。这告诉编译器不要为其创建函数序言/结语,您有义务自己编写这些,即添加保存/恢复此函数使用但声明由 EABI 保留的寄存器的代码。通过将执行函数调用的内联程序集“外包”到static inline __attribute__((naked))函数中,您可以避免必须指定大量的clobber列表,因为编译器会识别出它是一个函数调用(并根据需要在它周围保留/恢复,即使在内联代码时也是如此)。

于 2012-08-06T10:04:27.403 回答
0

获取 ABI 所需信息的简单解决方案(例如在哪些寄存器中获取传递的值):只需编写几行调用 c++ 方法的虚拟代码,然后反汇编结果(在您的目标平台上)。

于 2012-08-05T11:07:34.737 回答
0

我不太确定你在用那里的堆栈指针做什么 - 这是你在 ARM 上不需要的 x86 习惯用法,还是你故意尝试设置一个新的堆栈指​​针?

在任何情况下,堆栈指针都在r13- 程序计数器是r15-LDRMOV进入PC分支。在函数序言之外,SP 已经指向堆栈上的下一个位置,因此如果由于寄存器不足而需要在堆栈上传递参数时,您只需要修改它r0-r3- 这不是这里的情况。

如果您确实修改了堆栈指针,则需要在函数调用后恢复它,否则在退出函数时会出现一个不错的小崩溃。

最后,您需要将 ARM [E]ABI 允许被调用者在函数调用上修改的所有寄存器声明为已破坏。这是r0-r3, r9{也许} 和r12

如果您在 iOS 上执行此操作,ISTR 会在寄存器使用方面存在细微差异。

于 2012-08-05T10:50:52.683 回答
0

看看这个。虽然它使用 x86 程序集,但同样适用于 arm 程序集。

于 2012-08-05T00:51:10.253 回答