5

我需要通过知道它的地址来调用 C 中的函数,并且没有关于它的原型的信息(我不能将它转换为 C 函数指针)。

我对这个函数的信息是它的地址。

我也知道我想传递给它的参数(感谢 void 指针)和参数数组的大小(通过 void 指针访问)。

我也想尊重 C 调用约定。对于 x86 版本,我几乎知道该怎么做(在堆栈上分配空间,将参数复制到该空间,最后调用函数)。

问题在于 x64 约定(目前是 Linux 约定),其中参数通过寄存器传递。我不知道要适当填充寄存器的每个参数的大小,我只知道参数数组的大小。

另外,我不想依赖 gcc,所以我不能使用 __builtin_apply 这似乎不标准而且很黑。

我想编写自己的代码来支持多编译器并学习有趣的东西。

所以基本上,我想编写的函数与 __builtin_apply 的原型相同,即:

void *call_ptr(void (*fun)(), void *params, size_t size);

我还希望代码用 C 语言(感谢 asm inline)或纯 x64 asm 编写。

那么有没有办法在调用约定方面正确地做到这一点?或者在不确切知道函数原型的情况下,这在 x64 约定中是不可能的吗?

4

2 回答 2

2

特别是对于 Linux 上的 x64 调用约定,这根本不起作用。

原因是非常复杂的调用约定。

一些例子:

void funcA(float64 x);
void funcB(int64 x);

在这两种情况下,值“x”以不同的方式传递给函数,因为浮点和整数被传递给不同寄存器中的函数。

void funcC(float64 x,int64 y);
void funcD(int64 y,float64 x);

在这两种情况下,参数“x”和“y”的顺序不同。但是它们以相同的方式传递给函数(两个函数对“x”使用相同的寄存器,对“y”使用相同的寄存器)。

结论:要创建一个执行您想要的功能的函数,您必须将包含每个参数的参数类型的字符串传递给汇编器函数。参数的数量/大小肯定是不够的。然而,这绝对是可能的——只要它只能在 Linux 上工作。

于 2013-08-27T06:06:39.557 回答
0

我认为,您的所有决定都不会支持多编译器,因为将参数传递给函数的机制(寄存器、它们的顺序、堆栈、内存)——它是编译器依赖特性......

于 2013-08-25T21:23:17.703 回答