-1

Xcode 4 で gcc コンパイラを使用してインテル スタイルのインライン アセンブリ コードを作成しています。インライン アセンブリ コードの一部を以下に示します。

_asm
{   
    mov eax, esp
    sub esp, 116
    and esp, ~15
    mov [esp+112], eax       
}

シップ モードでは、GCC は上記の 4 行の asm コードを次のようにコンパイルします。

mov    %esp,%eax
sub    $0x74,%esp
and    $0xfffffff0,%esp
mov    %eax,0x70(%esp)

まさに私が欲しいものです。ただし、デバッグモードでは、GCC はそのコードをコンパイルして

mov    %esp,%eax
mov    %eax,%esp
mov    %esp,%eax
mov    %eax,-0x28(%ebp)
mov    %esp,%eax
mov    %eax,%esp
sub    $0x74,%esp
mov    %esp,%eax
mov    %eax,-0x24(%ebp)
mov    %esp,%eax
mov    %eax,%esp
**and    $0xfffffff0,%esp**         
**mov    %esp,%eax**        **//changing the value of “eax”**
mov    %eax,-0x24(%ebp)
mov    %esp,%ecx
mov    %ecx,%esp
**mov    %eax,0x70(%esp)**  **//store a “dirty” value to address 0x70(%esp), which is not we want**

上記の問題を解決する 1 つの方法は、AT&T スタイルの命令を使用してインライン asm コードを書き直し、レジスターを clobbered リストに追加することです。しかし、書き直すコードが長すぎるので、この方法では非常に手間がかかります。

問題を解決するための他の効率的な方法はありますか? レジスタ「eax」を予約する必要があることを gcc コンパイラに認識させるには?

4

2 に答える 2

2

2 つの方法があります。

  1. これを解決する最善の方法は、gcc アセンブリ テンプレート機能を使用することです。次に、レジスタアロケータがレジスタを他の目的で使用しないように、コンパイラに何をしているのかを伝えることができます。

  2. クイックハックは、「asm」の代わりに「asm volatile」を使用することです。これにより、gcc はそのブロック内の命令を再スケジュールしません。レジスタを使用していることをGCCに伝える必要があるため、レジスタには何も保存されません。clobber リストに「memory」もリストする必要があります。これにより、gcc は、コード ブロックの前にロードした可能性のある値を信頼できないことがわかります。

    asm volatile( "コードはここに入る" : : : "eax", "esp", "memory" );

ところで: あなたのコードは、esp を移動するなどの「悪いこと」を行っています。これは、自分が何をしているのかを正確に把握していない限り、後で問題を引き起こす可能性があります。

于 2012-04-24T11:12:22.760 に答える
-1

asm次のように、Intel スタイルのブロックの後の空のブロックが問題を解決します。

__asm volatile {   
    mov eax, esp
    sub esp, 116
    and esp, ~15
    mov [esp+112], eax       
};
__asm__ __volatile__ ("":::"eax", "memory");

ただし、元に戻さない%espと大変なことになります。

于 2016-09-27T14:45:00.073 に答える