使用asm的引用参数调用C++成员函数

Cha*_*vak 5 c++ x86 assembly

我想通过asm块调用C++成员函数.编译器是MSVC++(VS2008),可移植性不是问题.我必须为嵌入式系统构建一个远程/ RMI类型机制.客户端发送对象名称,方法名称,参数(序列化),我需要将方法调用到适当的对象.我可以从PDB文件中获取的类型信息.我需要编写一个通用的Invoke函数.我坚持如何调用一个以对象作为参数的成员函数.Specifially.我无法获得复制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];

   }

}
Run Code Online (Sandbox Code Playgroud)

Jes*_*ter 2

由于复制构造函数是非虚拟的,因此您只需按名称查找并调用它即可。了解编译器如何破坏复制构造函数,以及如何按名称解析符号(您可能对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;
}
Run Code Online (Sandbox Code Playgroud)

测试运行:

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
Run Code Online (Sandbox Code Playgroud)