Avatar billede krismort Nybegynder
22. maj 2006 - 22:18 Der er 10 kommentarer

metode til asm

Hej,
Er der en som kan hjælpe mig med at hvordan asm koden til at kalde foo fra instancen c skal se ud i msvc 7.0.

class I {
public:
  virtual void foo() = 0;
};

class C {
public:
  virtual ~C() {}
  void foo() {}
};

void main() {
  C c;
  c.foo();
  __asm {
    ???
  }
}
Avatar billede driis Nybegynder
22. maj 2006 - 22:48 #1
Nogen bestemt grund til at du vil gøre det i asm ?

Umiddelbart vil jeg tro, at du skal finde det name-manglede navn for funktionen og placere en call instruktion i din __asm blok.
http://www.kegel.com/mangle.html
Avatar billede mxs Nybegynder
22. maj 2006 - 22:49 #2
Hmmm hvis du får asm koden spyttet ud på en eller anden måde kan du vel lave et hop til linjen hvor foo starter?
Avatar billede arne_v Ekspert
23. maj 2006 - 02:51 #3
http://msdn2.microsoft.com/en-us/library/bdd5392d.aspx

antyder at det kan være et stort problem
Avatar billede krismort Nybegynder
23. maj 2006 - 19:13 #4
okay, hvis jeg for eksempel har  disse klasser og bytter rundt på vtable ved at gøre således så vil koden i D::foo() blive kørt istedet for C::foo() efter at linien : ((wrap*)c_obj)->vptr = ((wrap*)stub)->vptr; har byttet om på pointeren til vtable.
class Interface {
public:
    virtual void foo() = 0;
};

class C : public Interface {
public:
    C() {}
    virtual ~C() {}
    void foo() {
        cout << "c impl" << endl;
    }
};

class C_Stub : public Interface {
public:
    C_Stub() {}
    virtual ~C_Stub() {}
    void foo() {
        cout << "stub impl" << endl;
    }
};

struct vtable {
};

struct wrap {
    vtable* vptr;
};

void main() {
  C_Stub* stub = new C_Stub();
  C* c_obj = new C();
  ((wrap*)c_obj)->vptr = ((wrap*)stub)->vptr;
}

Problemet er så at hvis jeg opretter en instans som :
void main() {
  C c;
}
Og prøver at gøre det ssamme vil følgende ikke fungerer.. spørgsmålet ligger så i hvad der er til forskel fra at arbejde med en local instans og en instans oprettet med new operatoren.
( I MSVC 7.0, det er ligemeget om det fungerer på andre kompilerer )
Avatar billede krismort Nybegynder
23. maj 2006 - 19:14 #5
sorry i den tildligerer kommentar refererer jeg til D::foo der mente jeg self. C_Stub::foo()
Avatar billede arne_v Ekspert
23. maj 2006 - 19:19 #6
du bruger

C c;
((wrap*)&c)->vptr = ((wrap*)stub)->vptr;

?
Avatar billede krismort Nybegynder
23. maj 2006 - 21:24 #7
sådan her ser den kode jeg kører ud lige nu:

// vtable_hacking.cpp
#include <iostream>
#include <tchar.h>
#include <iostream>
#include <cstdlib>
#include <iostream>
#include <cstdarg>
using namespace std;

void* addressOf( int dummyarg, ... ) {
    void* ret=0;
    va_list args;
    va_start( args, dummyarg );
    ret = va_arg( args, void* );
    va_end(args);
    return ret;
}

class Interface {
public:
    virtual void foo() = 0;
};

class C : public Interface {
public:
    C() {}
    virtual ~C() {}
    void foo() {
        cout << "virker ikke" << endl;
    }
};

class C_Stub : public Interface {
public:
    C_Stub() {}
    virtual ~C_Stub() {}
    void foo() {
        cout << "virker fint." << endl;
    }
};

struct vtable {
};

struct wrap {
    vtable* vptr;
};


void main() {
    C_Stub* stub = new C_Stub();
   
    // virker fint.
    C* c_obj = new C();
    ((wrap*)c_obj)->vptr = ((wrap*)stub)->vptr;
    c_obj->foo();

    // virker ikke.
    C c_obj2;
    ((wrap*)&c_obj2)->vptr = ((wrap*)stub)->vptr;
    c_obj2.foo();

    // virker fint.
    C* c_obj3 = new C();
    ((wrap*)c_obj3)->vptr = ((wrap*)stub)->vptr;
    (*c_obj3).foo();
    system("PAUSE");
}
Avatar billede arne_v Ekspert
24. maj 2006 - 02:20 #8
hvis man studerer den genererede kode vil man se at:

; 55  :    c_obj->foo();

    mov    edx, DWORD PTR _c_obj$[ebp]
    mov    eax, DWORD PTR [edx]
    mov    ecx, DWORD PTR _c_obj$[ebp]
    call    DWORD PTR [eax]

; 60  :    c_obj2.foo();

    lea    ecx, DWORD PTR _c_obj2$[ebp]
    call    ?foo@C@@UAEXXZ                ; C::foo


; 65  :    (*c_obj3).foo();

    mov    ecx, DWORD PTR _c_obj3$[ebp]
    mov    edx, DWORD PTR [ecx]
    mov    ecx, DWORD PTR _c_obj3$[ebp]
    call    DWORD PTR [edx]

når det er et local objekt og ikke en pointer, så slår den slet ikke op i vtable.

Der er der ingen grund til fordi den kender typen og den tror ikke at der kan ændres
i vtable.
Avatar billede arne_v Ekspert
18. juni 2006 - 20:49 #9
tid at få afsluttet her ?
Avatar billede krismort Nybegynder
03. oktober 2006 - 22:54 #10
jeps
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester