【发布时间】:2015-06-14 20:37:09
【问题描述】:
我有一个包含 32 位值的数组(nativeParameters,长度为 nativeParameterCount)和一个指向函数的指针(void* 指向 cdecl 函数,这里是 method->nativeFunction)应该被调用。现在我正在尝试这样做:
// Push parameters for call
if (nativeParameterCount != 0) {
uint32_t count = 0;
pushParameter:
uint32_t value = nativeParameters[nativeParameterCount - count - 1];
asm("push %0" : : "r"(value));
if (++count < nativeParameterCount) goto pushParameter;
}
// Call method
asm("call *%0" : : "r"(method->nativeFunction));
// Return value
uint32_t eax;
uint32_t edx;
asm("push %eax");
asm("push %edx");
asm("pop %0" : "=r"(edx));
asm("pop %0" : "=r"(eax));
uint64_t returnValue = eax;
// If the typesize of the methods return type is >4 bytes, or with EDX
Type returnType = method->returnType.type;
if (TYPE_SIZES[returnType] > 4) {
returnValue |= (((uint64_t) edx) << 32);
}
// Clean stack
asm("add %%esp, %0" : : "r"(parameterByteSize));
这种方法是否适合执行本机调用(假设所有目标函数只接受 32 位值作为参数)?我可以确定它不会破坏堆栈或弄乱寄存器,或者以其他方式影响正常流程吗?另外,还有其他方法吗?
【问题讨论】:
-
nativeParameterCount是什么?nativeParameters是什么?你为什么要gotoing 而不是使用for循环? -
让我们退后一步:你真正想用这个完成什么?你想调用一个你有函数指针的函数吗?
-
这完全不安全。例如,在编译器不知情的情况下推入堆栈可能会弄乱任何局部变量引用。你不应该为此使用内联 asm,编写一个单独的 asm 模块,你可以控制。
-
@maxdev 听起来您想使用汇编来编写此代码。 (或者如果你真的想用 C 来写,那么用 C, 而不是半 C 半汇编。)
-
此外,根据架构/平台,参数可能会在寄存器中传递,而不是被压入堆栈(例如,在x86-64 上)。
标签: c assembly virtual-machine inline-assembly vm-implementation