2013-01-15 7 views
5

Chcę wywołać funkcję członka C++ za pomocą bloków asm. Kompilatorem jest MSVC++ (VS2008), a przenośność nie jest problemem. Muszę zbudować mechanizm typu remoting/RMI dla systemu wbudowanego. Klient wysyła nazwę obiektu, nazwę metody, argumenty (serializowane) i muszę wywołać metodę do odpowiedniego obiektu. Informacje o typie, które mogę uzyskać z pliku PDB. Muszę napisać ogólną funkcję Invoke. Utknąłem, jak wywołać funkcję składową, która przyjmuje obiekt jako argument. Specyficznie. Nie mogę uzyskać wskaźnika do skopiowania ctor. Dowolny pomysł.Wywołanie funkcji członka C++ z argumentem odniesienia z asm

PS: Poniższy kod kompiluje i działa poprawnie do 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]; 

    } 

} 
+0

Ludzie tutaj: http://www.asmcommunity.net/board/index.php?topic=17897.0 wydaje się, że nie można uzyskać adresu konstruktora kopii. – us2012

Odpowiedz

2

Ponieważ konstruktor kopia nie jest wirtualny, to po prostu trzeba szukać go po imieniu i nazwać. Dowiedz się, w jaki sposób twój kompilator koduje konstruktorów, i jak rozróżniać symbole według nazwy (może Cię to interesować GetProcAddress).

Oto przykład Linux, ale należy pamiętać, że używa innej konwencji powołanie do visual studio: Uruchom

#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; 
} 

testu:

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 
+0

Dzięki. To zadziała dla mnie. – Charvak

0

Jester przewidzianego Jednym ze sposobów rozwiązania tego problemu. Znalazłem inny sposób, który jest specyficzny dla MSVC. Możemy użyć FUNCDNAME, aby uzyskać dekorowaną nazwę kopii ctor, a następnie pobrać prokadownię. Oto mój zmodyfikowany kod

#include <stdio.h> 
struct Point 
{ 
    static char* pointCopyCtorName; 
    int x; 
    int y; 
    Point() 
    { 
     if (!pointCopyCtorName) 
     { 
      // force copy ctor 
      Point(*this); 
     } 
     x = 10; 
     y =10; 
    } 
    __declspec(dllexport) Point(const Point& p) 
    { 
     if (!pointCopyCtorName) 
     pointCopyCtorName = __FUNCDNAME__; 
     if (this != &p) 
     { 
      x = p.x; 
      y = p.y; 
     } 
    } 

    virtual ~Point() 
    { 
    } 
}; 
char* Point::pointCopyCtorName = NULL; 



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); 

     } 

}; 


HMODULE GetCurrentModule() 
{ 
    HMODULE hMod = NULL; 
    GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, 
     (LPCTSTR) "GetCurrrentModule", &hMod); 
    return hMod; 
} 


void main() 
{ 
    C* c = new C; 
    Point p; 
    HMODULE hMod = GetCurrentModule(); 
    if (!hMod) 
     return; 

    FARPROC pPointCopyCtor = GetProcAddress(hMod, p.pointCopyCtorName); 
    if (!pPointCopyCtor) 
     return; 


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

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

    // c->funcObj(p); 
    __asm 
    { 
     sub esp, 12; 
     mov ecx, esp; 
     lea eax, p; 
     push eax; 
     call pPointCopyCtor; 
     mov ecx, c; 
     call [C::funcObj]; 
    } 

} 
Powiązane problemy