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

时间:2010-02-18 18:12:27

标签: assembly call inline-assembly

基本上,我希望能够做到这样的事情:

//assume myFunction is defined and takes one argument that is an int
char * functionName = "myFunction";
int arg = 5;

__asm{
    push a
    call functionName
}

基本上我想调用一个名字存储在字符串中的函数。这样做的正确语法是什么?

编辑: 我们正在谈论x86汇编

4 个答案:

答案 0 :(得分: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。

这是一个非常非常奇怪的想要完成的事情 - 你想解决什么问题?

答案 1 :(得分:1)

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

先发制人:是的,有时编译器可以将符号嵌入到可执行文件中然后可以搜索,但这是一个充满问题的方法。数据的格式可以在编译器版本之间改变,链接器可以删除信息等等。

答案 2 :(得分:0)

简短回答:忘了它,如果这是允许的话,这很可能实现得太难了。

更长的回答:我能想到的最简单的方法是创建一个查找表,将字符串映射到函数(或者更准确地说,映射到函数指针)。您首先需要考虑一个合理的数据结构来保存该映射,并实现一个字符串比较函数,以便在查找期间将functionName与键进行比较。最后但同样重要的是,您必须手动将映射条目加载到该表结构中。

(我不会再详细说明了,首先是因为我的汇编日已经过去了,其次是因为我有点好奇,想知道你是否达不到想要的东西与另一个更容易实施的解决方案有关...抱歉。)

答案 3 :(得分:0)

我不知道有什么方法可以轻易做到这一点。在某些更高级别的语言中,您可以使用反射来实现此目的,但C和汇编都没有可用的功能。到链接器完成时,所有函数调用都被解析为地址。也许如果您可以访问某些调试基础结构,可以对函数名进行反向查找以获取其地址,但从汇编中实现这一点并非易事。

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