2011-01-03 4 views
1

Frage: Wie kann ich auf eine Elementvariable in Assembly aus einer Nicht-POD-Klasse zugreifen?Zugreifen auf C++ - Klassenelement in Inline-Assembly


Herstellung:

ich einige Inline-Assembler-Code für eine Klasse-Memberfunktion geschrieben, aber was mir entzieht sich, wie Klasse Membervariablen zugreifen. Ich habe versucht, die offsetof Makro, aber das ist eine Nicht-POD-Klasse.

Die aktuelle Lösung, die ich verwende, ist, einen Zeiger aus dem globalen Bereich auf die Elementvariable zuzuweisen, aber es ist eine unordentliche Lösung und ich hatte gehofft, dass es etwas Besseres gibt, von dem ich nichts weiß.

Hinweis: Ich verwende den G ++ - Compiler. Eine Lösung mit Intel Syntax Asm wäre nett, aber ich nehme alles.

Beispiel dafür, was ich (Intel-Syntax) zu tun:

class SomeClass 
{ 
    int* var_j; 
    void set4(void) 
    { 
    asm("mov var_j, 4"); // sets pointer SomeClass::var_j to address "4" 
    } 
}; 

aktuelle hackish Lösung:

int* global_j; 
class SomeClass 
{ 
    int* var_j; 
    void set4(void) 
    { 
    asm("mov global_j, 4"); // sets pointer global_j to address "4" 
    var_j = global_j;  // copy it back to member variable :(
    } 
}; 

Das sind grobe Beispiele, aber ich denke, dass sie den Punkt zu vermitteln .

+3

Haben Sie versucht, eine Disassemblierung dessen zu betrachten, was der G ++ - Compiler mit dem Code 'var_j = 4;' oder so ähnlich ausgibt? –

+0

die Verwendung eines globalen Zeigers ist nicht threadsicher, da der Wert möglicherweise überschrieben wird, bevor der gespeicherte Wert neu zugewiesen wird – xmoex

Antwort

6

Dies alles, was Sie brauchen:

__asm__ __volatile__ ("movl $4,%[v]" : [v] "+m" (var_j)) ; 

Edited hinzufügen: Der Assembler akzeptiert Intel-Syntax, aber der Compiler kennt es nicht, so dass dieser Trick wird mit Intel-Syntax nicht (nicht mit g ++ 4.4.0, sowieso).

+0

Dies ist sehr interessant. Diese Syntax ist nicht Teil des Inline Assembly HOWTOs. Wo hast du davon erfahren? – user434507

+0

"Verwenden der GNU-Compiler-Sammlung" (für gcc-Version 4.5.1), Abschnitt 6.39 "Assembler-Anweisungen mit C-Ausdruck-Operanden". Verfügbar unter http://gcc.gnu.org/onlinedocs/gcc/. (Eigentlich kann ich meine Version im Internet nicht finden - in diesem Dokument ist es Abschnitt 6.41.) – TonyK

3
class SomeClass 
{ 
    int* var_j; 
    void set4(void) 
    { 
    __asm__ __volatile__("movl $4, (%0,%1)" 
: 
: "r"(this), "r"((char*)&var_j-(char*)this) 
: 
); 
    } 
}; 

Dies könnte auch funktionieren, können Sie ein Register zu speichern:

__asm__ __volatile__("movl $4, %1(%0)" 
: 
: "r"(this), "i"((char*)&var_j-(char*)this) 
: 
); 

In der Tat, da der Versatz von var_j WRT. this sollte zur Kompilierungszeit bekannt sein, die zweite Option ist der Weg zu gehen, auch wenn es einige Feinabstimmungen benötigt, um es zum Laufen zu bringen. (Ich habe gerade keinen Zugang zu einem g ++ System, also überlasse ich es Ihnen, das zu untersuchen.)

Und unterschätzen Sie niemals die Wichtigkeit von __volatile__. Ich brauchte mehr Zeit, um Bugs aufzuspüren, die auftauchten, weil ich das flüchtige Schlüsselwort verpasste und der Compiler es auf sich nahm, seltsame Dinge mit meiner Assembly zu tun.