【问题标题】:Call function from shared library in GCC with inline assembler使用内联汇编器从 GCC 中的共享库调用函数
【发布时间】:2012-02-22 19:41:12
【问题描述】:

我已经创建了共享库(将像插件一样使用)。有很多函数,比如a

extern "C" long __attribute__ ((__cdecl__)) SumAgrs(long X, long Y, long Z, long *Out)
{
    *Out = X + Y + Z;
    return 0;
}

我想在 C++(GCC,Linux)中调用这个库中的函数,但不是在编译时。当我使用内联汇编程序时,“push”指令会破坏局部变量,我不知道如何修复它。

typedef int (*FARPROC)();

void *dl_handle = dlopen("plugin.so", RTLD_LAZY);
FARPROC proc = (FARPROC)dlsym(dl_handle, "SumAgrs");

long result;

asm("leal %0, %%eax\n\r" \
    "pushl %%eax" : : "m" (result));
asm("pushl $10");
asm("pushl $15");
asm("pushl $20");
asm("call *%0" : : "m" (proc));

结果二进制文件包含类似 call *24(%esp) 的内容。所以我的 pushl 更改 %espcall 导致分段错误。但是如何避免这种行为呢?

谢谢

【问题讨论】:

    标签: c++ gcc assembly call shared


    【解决方案1】:

    看看 libffi:“一个可移植的外部函数接口库”

    “libffi 库为各种调用约定提供了一个可移植的高级编程接口。这允许程序员在运行时调用调用接口描述指定的任何函数。”

    http://sourceware.org/libffi/

    【讨论】:

      【解决方案2】:

      实际上,你不需要汇编程序来调用函数:

      extern "C" 
      {
          typedef long __attribute__ ((__cdecl__)) (*Proc)(long X, long Y, long Z, long *Out);
      }
      
      void *dl_handle = dlopen("plugin.so", RTLD_LAZY);
      Proc proc = (Proc)dlsym(dl_handle, "SumAgrs");
      
      proc(...); // call
      

      请注意,无论您使用 c 代码还是使用 ASM 内联调用函数,您的调用代码都是在 编译 时间生成的。您不能将string 变量传递给asm,因为您的asm 内联代码应该在程序编译期间生成。这意味着你不能这样做

      std::string asm_code;
      std:: cin >> asm_code;
      asm(asm_code);
      

      【讨论】:

      • 函数将从脚本中调用,参数存储在数组中。所以编译时“调用”不是解决方案。
      • no no,使用 ASM 内联,代码将在运行时生成。例如(伪代码): foreach (params) { push parm; } 调用函数;
      • @user1173308,你不能那样做!您永远无法确定,foreach(params) 没有在其中使用堆栈指针,当然,它不假设您会手动更改它! 不要写这样的代码
      猜你喜欢
      • 2011-12-20
      • 1970-01-01
      • 1970-01-01
      • 2011-03-27
      • 1970-01-01
      • 1970-01-01
      • 2011-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多