0

これは簡単な質問だと思いますが、何も見つかりませんでした。私が書くなら

void bar()
{
    {
        void *rax = 0/* ...*/, *rbx = 0/* ... */;
        asm volatile ("movq %0, %%rax; movq %1, %%rbx;" : : "m"(rax), "m"(rbx));
        goto foo;    
    }

    {
        foo:
        void* rax, *rbx;
        asm volatile ("movq %%rax, %0; movq %%rbx, %1;" : "=m"(rax), "=m"(rbx));

        // LOTS OF CODE
    }
}

2 番目のブロック内の他のコードが実行される前に、rax/rbx の値をフェッチできることが保証されていますか?

4

2 に答える 2

3

いいえ -- コンパイラは、asm ステートメントの直前/直後に割り当てたレジスタ/メモリ位置への制約に基づいて、in/out 値を接続し、他のレジスタは影響を受けないと想定します。したがって、あなたの場合、何か重要なものを入れ%%eaxたり%%ebx、壊したりしている可能性があります(クラッシュやその他の不正行為を引き起こす可能性があります)。

asm ステートメントで固定レジスタを使用するときはいつでも、それらのレジスタを clobbers リストにリストする必要があります (特定のレジスタにマップする制約を使用している場合を除く)。したがって、少なくとも次のものが必要です。

asm volatile ("movq %0, %%rax; movq %1, %%rbx;" : : "m"(rax), "m"(rbx) : "rax", "rbx");

%%eaxasm ステートメントの場合 - しかし、それでも、コンパイラーが最初の asm ブロックの中または後、2 番目のブロックの前に何か他のものを入れないという保証はありません%%ebx(保存しようとしている値を破壊します)。

于 2013-07-03T00:31:11.793 に答える
1

volatilegcc でwithを使用するasmと、コンパイラがステートメントを並べ替えないことが保証されます。foo:ただし、コンパイラがラベルとインラインasmステートメントの間に余分なコードを追加しないという保証はありません。そしてもちろん、これはレジスタ値がそのセクションに保存されていることに依存できないことを意味します-私はその明確な例を思い付くことができませんでしたが、コンパイラがこれができることを保証していないことはかなり確信しています起こりません。

于 2013-07-03T09:21:06.697 に答える