2011-01-03 3 views
1

質問:非PODクラス内からアセンブリ内のメンバー変数にアクセスするにはどうすればよいですか?インラインアセンブリ内のC++クラスメンバーへのアクセス


推敲:

私はクラスのメンバ関数のためのいくつかのインラインアセンブリコードを書かれたが、どのような私を見逃さすることは、クラスのメンバ変数にアクセスする方法ですしています。私はオフセットマクロを試しましたが、これは非PODクラスです。

私が使用している現在の解決策は、グローバルスコープからメンバ変数へのポインタを割り当てることですが、それは面倒な解決策であり、私が知っていないより良いものがあることを期待していました。

メモ:私はG ++コンパイラを使用しています。 Intelの構文Asmの解決策はいいかもしれませんが、私は何でも取っていきます。私は(インテル構文を)やりたいことの

例:

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

現在のハックソリューション:

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 :(
    } 
}; 

ものは、粗例ですが、私は、彼らは全体のポイントを得ると思います。

+3

G + +コンパイラが出力するコードを 'var_j = 4;'というようなコードで逆アセンブルしようとしましたか? –

+0

グローバルポインタを使用してスレッドセーフではありません。保存された値を再割り当てする前に値が上書きされる可能性があります。 – xmoex

答えて

6

これはあなたが必要とするすべてである:

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

編集追加する:アセンブラがインテルの構文を受け入れていますが、コンパイラはそれを知らないので、このトリックは(インテル構文を使用して動作しません。とにかくg ++ 4.4.0ではなく)。

+0

これは非常に興味深いものです。この構文は、標準のGCCインラインアセンブリHOWTOの一部ではありません。あなたはどこでそれについて学びましたか? – user434507

+0

「GNUコンパイラ・コレクションの使用」(gccバージョン4.5.1の場合)、第6.39項「C式のオペランドを含むアセンブラ命令」 http://gcc.gnu.org/onlinedocs/gcc/から入手できます。 (実際に私のバージョンはウェブ上に見つからないようです - この文書では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) 
: 
); 
    } 
}; 

これはあなたに1つのレジスタを保存し、あまりにも動作するかもしれません。実際には

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

を、var_j WRTのオフセット以来。コンパイル時にthisを知らなければなりません.2番目のオプションは、動作させるためにいくつかの微調整が必​​要な場合でも、移動する方法です。 (私は今g ++システムにアクセスできないので、調査するためにこれをあなたに任せておきます)

そして、__volatile__の重要性を過小評価してはいけません。私が揮発性のキーワードを見逃していたために現れたバグを追跡したいと思っていた時代をさらに踏襲し、コンパイラーは自分のアセンブリで奇妙なことをするためにそれを取った。