如何在内联汇编中将字符串作为参数传递给“call”指令?

3
基本上,我想要能够做这样的事情:
//assume myFunction is defined and takes one argument that is an int
char * functionName = "myFunction";
int arg = 5;

__asm{
    push a
    call functionName
}

基本上,我希望能够调用存储在字符串中的函数名称。如何正确地实现这个语法?

编辑: 我们正在讨论x86汇编。


重新表述问题。你所说的“单个int作为参数char *_”是什么意思?你忽略了一个重要的细节——你想要什么样的处理器?你是想要一个概括性的想法还是实际的类似x86汇编代码? - dirkgently
我不理解这个示例。调用不能是一个字符串,必须是函数指针。你需要获取指向该函数的指针才能调用它。一种可能性是在您自己的DLL上使用GetProcAddr。 - Steven Sudit
抱歉造成困惑,我的意思是该函数接受一个 int 类型的参数:被调用的函数并不重要,我只是解释为什么要将 "a" 推入堆栈。 - Emil D
3个回答

1

你不能直接这样做。

call函数需要一个地址作为参数。即使你写了"call functionName",链接器也会将functionName替换为函数的实际地址。你需要先将该字符串映射到其地址。一般来说,C和C++不支持任何关于函数名称映射的运行时元数据,因此无法实现这一点。如果该函数是从DLL中导出的,可以使用GetProcAddress来查找其地址。

如果函数列表是静态的,你可以自己提前创建映射。

类似于:

std:map<string, PVOID> functionMappings;
functionMappings["MyFunction"] = MyFunction;


// Later


PVOID function = functionMappings["MyFunction"];

__asm
{
    push a;
    call [function]
}

一些注释:
我相信标准规定函数指针可能比PVOID更大。这应该适用于Windows x86/x64平台。
您没有说明使用哪种调用约定-此代码假定为stdcall。
这是一个非常奇怪的事情,想要实现什么问题?

我猜我需要使用GetProcAddress。如果这是一个愚蠢的问题,那我很抱歉,但是这个函数的返回值类型到底是什么?例如,下面的代码是否可行:int a = GetProcAddress(dllHandle, "myFunction"); - Emil D
顺便问一下,代码中有什么表明__stdcall吗?仅仅是调用者没有从栈中弹出参数这一事实吗,还是还有其他的东西? - Emil D
__stdcall 是一种调用约定 - 如果你在编写包含函数调用的汇编代码,你需要了解调用约定。网络上有很多关于 GetProcAddress 和调用约定的资源。MSDN甚至提供了演示如何使用GetProcAddress返回值的示例代码。 - Michael

1

这是不可能的,你正在尝试进行一个按名称调用的操作。汇编只有按值调用,其中值是一个地址。您需要将名称转换为地址,并将地址传递给汇编程序,这意味着您需要一些名称和地址之间的交叉引用。编译器可以在这里帮助您,在C和C ++中,您需要查找函数指针以查看获取函数地址所需语法,然后可以将其传递给汇编程序。

预测性:是的,有时编译器可以将符号嵌入可执行文件中,然后可以通过搜索进行查询,但这是一个充满问题的方法。数据的格式可能因编译器版本不同而更改,信息可能会被链接器剥离等等。


0

我不知道有什么简单的方法来做这个。在一些高级语言中,您可以使用反射来实现此目的,但是C和汇编语言都没有这种功能。当链接器完成所有函数调用的解析时,它们都被转换为地址。也许如果您有访问某些调试基础设施的权限,您可以通过函数名的反向查找来获取其地址,但这并不容易从汇编语言实现。

或者,您可以在编译时定义函数指针来存储您感兴趣的函数的地址(尽管您仍然需要一种方法将字符串转换为函数指针,可能是通过字符串比较表查找)。如果您对此感兴趣,我建议先编写C等效代码,然后查看编译器输出的汇编代码,以了解它如何处理函数指针。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接