调用具有不同 arg 计数的函数
Calling functions with different arg count
我正在反编译一个非常古老的游戏,我的目标是恢复 100% 的本机代码。因此,我需要尽可能多地保留现有架构(例如,仅使用 std::function
并不是很有帮助)。
我有一组 static 函数,它们具有不同数量的参数。它们存储在这样的结构中:
struct ScriptFunction
{
const wchar_t* m_name;
void* m_func; // ptr to specific function
void* m_returnType;
int m_argCount;
};
并且是这样填充的:
ScriptFunction s_functions[206] = {
{L"AddMoveAroundDesire", &ScriptFunctions::AddMoveAroundDesire, &CScriptType::s_void, 2},
{L"AddDoNothingDesire", &ScriptFunctions::AddDoNothingDesire, &CScriptType::s_void, 2},
{L"AddAttackDesire", &ScriptFunctions::AddAttackDesire, &CScriptType::s_void, 3},
{L"AddAttackDesireEx", &ScriptFunctions::AddAttackDesireEx, &CScriptType::s_void, 4},
{L"AddGetItemDesire", &ScriptFunctions::AddGetItemDesire, &CScriptType::s_void, 2},
...
那么,我如何调用 ScriptFunction::m_func 给定 m_argCount 和 void** 参数?我必须以某种方式将参数压入堆栈并调用函数调用,但我不知道。
一些汇编代码? va_list?但是如何在运行-时间填写呢?
更新:调用者看起来像这样
void CScriptAccessible::InvokeInternal(ScriptFunction* scriptFunc, void** args)
{
// here I have to push params from **args** to stack
// and somehow call ScriptFunction::m_func
// In assembly I could see pushes to stack in a loop (driven by
// ScriptFunction::m_argCount). But I'm wondering, whether it's
// possible to do in C++ (push args on stack and call function by just address)
}
在该语言中,只有 switch
/cast 解决方案。这让编译器生成正确的调用约定: 例如 ,在 x86-64 Linux 上,前几个参数在预定义的寄存器中传递。 (优化器可能会将不同的路径合并为跳转到您所期望的那种展开的循环中。)还要记住,仅在 C/C++ 中,根本没有“堆栈”。
顺便说一句,也不能保证将 void*
用于函数(因为它可以指向任何 对象 但它们不是对象),尽管它通常有效(并且POSIX 需要 dlsym
).
我正在反编译一个非常古老的游戏,我的目标是恢复 100% 的本机代码。因此,我需要尽可能多地保留现有架构(例如,仅使用 std::function
并不是很有帮助)。
我有一组 static 函数,它们具有不同数量的参数。它们存储在这样的结构中:
struct ScriptFunction
{
const wchar_t* m_name;
void* m_func; // ptr to specific function
void* m_returnType;
int m_argCount;
};
并且是这样填充的:
ScriptFunction s_functions[206] = {
{L"AddMoveAroundDesire", &ScriptFunctions::AddMoveAroundDesire, &CScriptType::s_void, 2},
{L"AddDoNothingDesire", &ScriptFunctions::AddDoNothingDesire, &CScriptType::s_void, 2},
{L"AddAttackDesire", &ScriptFunctions::AddAttackDesire, &CScriptType::s_void, 3},
{L"AddAttackDesireEx", &ScriptFunctions::AddAttackDesireEx, &CScriptType::s_void, 4},
{L"AddGetItemDesire", &ScriptFunctions::AddGetItemDesire, &CScriptType::s_void, 2},
...
那么,我如何调用 ScriptFunction::m_func 给定 m_argCount 和 void** 参数?我必须以某种方式将参数压入堆栈并调用函数调用,但我不知道。
一些汇编代码? va_list?但是如何在运行-时间填写呢?
更新:调用者看起来像这样
void CScriptAccessible::InvokeInternal(ScriptFunction* scriptFunc, void** args)
{
// here I have to push params from **args** to stack
// and somehow call ScriptFunction::m_func
// In assembly I could see pushes to stack in a loop (driven by
// ScriptFunction::m_argCount). But I'm wondering, whether it's
// possible to do in C++ (push args on stack and call function by just address)
}
在该语言中,只有 switch
/cast 解决方案。这让编译器生成正确的调用约定: 例如 ,在 x86-64 Linux 上,前几个参数在预定义的寄存器中传递。 (优化器可能会将不同的路径合并为跳转到您所期望的那种展开的循环中。)还要记住,仅在 C/C++ 中,根本没有“堆栈”。
顺便说一句,也不能保证将 void*
用于函数(因为它可以指向任何 对象 但它们不是对象),尽管它通常有效(并且POSIX 需要 dlsym
).