c++ - 使用来自 asm 的引用参数调用 C++ 成员函数

标签 c++ assembly x86

我想通过 asm block 调用 C++ 成员函数。编译器是 MSVC++ (VS2008),可移植性不是问题。我必须为嵌入式系统构建一个远程处理/RMI 类型的机制。客户端发送对象名称、方法名称、参数(序列化),我需要将方法调用到适当的对象。我可以从 PDB 文件中获取的类型信息。我需要编写一个通用的 Invoke 函数。我被困在如何调用一个以对象为参数的成员函数上。特别地。我无法获得复制 ctor 的指针。任何想法。

PS:下面的代码可以为 C::funcRef 正确编译和运行

#include <stdio.h>
struct Point
{
   int x;
   int y;
   Point() 
   { 
       x = 10; 
       y =10;
   }
   Point(const Point& p)
   {
       x = p.x;
       y = p.y;
   }
   virtual ~Point() 
   {
   }
};

class C
{
 public:
     void funcRef(Point& p) 
     { 
         printf("C::funcRef\n x= %d, y =%d\n", p.x, p.y);
     }
     void funcObj(Point p) 
     { 
         printf("C::funcObj\nx = %d y = %d\n", p.x, p.y); 

      }

};




void main()
{
   C* c = new C;
   Point p;



   //c->funcRef(p);
   // this works
   __asm
   {

      lea eax, p;
      push eax; 
      mov ecx, c;
      call [C::funcRef];

   }

  // c->funcObj(p); 
   __asm 
   {
       sub esp, 12; // make room for sizeof(Point)
       mov ecx, esp; 
       lea eax, p;
       push eax;
       // how to call copy ctor here
       mov ecx, c;
       call [C::funcObj];

   }

}

最佳答案

由于复制构造函数是非虚拟的,您只需按名称查找并调用它即可。了解您的编译器如何破坏复制构造函数,以及如何按名称解析符号(您可能对 GetProcAddress 感兴趣)。

这是一个 linux 示例,但请注意它使用与 visual studio 不同的调用约定:

#include <stdio.h>
#include <dlfcn.h>

struct Point
{
   int x;
   int y;
   Point()
   {
       printf("Default constructing point @%p\n", this);
       x = 10;
       y = 10;
   }
   Point(const Point& p) __attribute__((used, visibility("default")))
   {
       printf("Copy constructing point @%p from point @%p\n", this, &p);
       x = p.x;
       y = p.y;
   }
   virtual ~Point()
   {
       printf("Point @%p destroyed\n", this);
   }
};

class C
{
 public:
     void funcRef(Point& p)
     {
         printf("C::funcRef\n x= %d, y =%d\n", p.x, p.y);
     }
     void funcObj(Point p)
     {
         printf("C::funcObj p = %p, x = %d, y = %d\n", &p, p.x, p.y);

      }

};

typedef void (C::*FRef)(Point&);
typedef void (C::*FObj)(Point);

int main()
{
   C* c = new C;
   Point p;

   FRef _fref =  &C::funcRef;
   FObj _fobj =  &C::funcObj;

//   c->funcObj(p);
   void* self = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
   printf("Module handle for self is %p\n", self);
   // mangled name of Point::Point(const Point&)
   void* constructor = dlsym(self, "_ZN5PointC1ERKS_");
   printf("Constructor address is %p\n", constructor);
   void* dummy;
   __asm__ __volatile__ (
      "sub esp, 32\n\t"
      "mov [esp+4], %[p] # argument to copy constructor\n\t"
      "lea eax, [esp+20]\n\t"
      "mov [esp], eax # this pointer\n\t"
      "call %[constructor] # construct instance at [esp+20]\n\t"
      "lea eax, [esp+20]\n\t"
      "mov [esp+4], eax # argument to function\n\t"
      "mov [esp], %[c] # this pointer\n\t"
      "call %[fobj]\n\t"
      "lea eax, [esp+20]\n\t"
      "mov [esp], eax # this pointer\n\t"
      "mov eax, [eax] # vtable\n\t"
      "call [eax] # destructor\n\t"
      "add esp, 32 # free rest of stack\n\t"
      : "=a" (dummy), "=c" (dummy)
      : [p] "a" (&p), [c] "S" (&c), [fobj] "D" ((void*)_fobj), [constructor] "c" (constructor)
      : "edx");
   return 0;
}

测试运行:

Default constructing point @0xffc145e4
Module handle for self is 0xf77fb900
Constructor address is 0x8048c02
Copy constructing point @0xffc145b4 from point @0xffc145e4
C::funcObj p = 0xffc145b4, x = 10, y = 10
Point @0xffc145b4 destroyed
Point @0xffc145e4 destroyed

关于c++ - 使用来自 asm 的引用参数调用 C++ 成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14346576/

相关文章:

c++ - 在运行时选择相同功能的版本

c++ - Mac OS X 上的 CGAL 链接错误

c++ - 隐式转换和复制构造函数

assembly - 错误 LNK2019 : unresolved external symbol __imp____acrt_iob_func referenced in function _printf in VS2019

assembly - 引导加载程序在真实硬件上打印垃圾

android - 为 x86 编译的 APK 可以上传到 Amazon Appstore 吗?

c++ - 为什么 MSVC 在执行此位测试之前会发出无用的 MOVSX?

c++ - 如何在QTabWidget标题中设置QWidget?

assembly - x86 汇编编码中的宏

c - 组装时如何返回?