3

次のコードを検討してください。

#include <stdio.h>

void main() {
    uint32_t num = 2;

    __asm__ __volatile__ ("CPUID");
    __asm__ __volatile__ ("movl $1, %%ecx":);
    __asm__ __volatile__ ("andl $0, %%ecx": "=r"(num));

    printf("%i\n", num);
}

私の最初の期待は、このコードが出力されることでした。行0をコメントアウトすると出力されますCPUIDが、そのままではゴミが発生していました。試行錯誤と調査の結果、ランダム レジスタの値を取得していることに気付きました。どうやらGCCは、実行されたステートメントの結果が欲しいとは想定していません。

問題は、他のレジスタで何が起こっているかに関係なく、AND の結果を適切に取得するステートメントに依存する (他の人の) コードを見たことです。私の観察によると、明らかにそのようなコードは壊れており、"=r"を に置き換える必要があり"=c"ます。

"=r"私の質問は、一貫して、または明白な期待に従って動作する制約に頼ることができるでしょうか? それとも、GCC の実装があまりにも不透明/奇妙/その他であり、あらゆる状況でそれを避けるのが最善ですか?

4

1 に答える 1

2

出力指定子を使用するには、=rgcc が使用したいレジスタを自由に選択できるようにする必要があります。これを行うには、入力と出力を一般的に で指定し、最初%0の入力で始まる入力を指定し%1ます。

あなたの場合、あなたはそれnumがレジスターにある可能性があると言っています。ただし、出力レジスタを使用する asm 命令には何もありません。したがって、gcc は基本的にこれを無視します。

CPUID命令をコメントするかコメントしないと異なる値が得られる理由は、 、、、およびにCPUID書き込むことができるためです。私のシステムであなたの例を試してみたところ、両方の場合で結果が得られました。しかし、生成されたアセンブリが の値を出力していることに気付きました。だから、私がこのプログラムを実行したとき、に書いていたと思います。eaxebxecxedx0eaxCPUID0eax

=r制約を使用したい場合は、次のようにする必要があります。

  asm("CPUID \n\t"
      "movl $1, %0 \n\t"
      "andl $0, %0 \n\t"
      :"=r"(num) );

それ以外の場合、asm コードでレジスタが明確に言及されている場合は、制約リストでそれを指定する必要があります。あなたの例では、それはを使用することを意味し=cます。

于 2012-05-29T22:27:53.850 に答える