3

この質問を読んだとき、誰かが(何年も前に)アセンブラーの観点から、これらの2つの操作は非常に異なると私に言ったことを思い出しました。

n = 0;

n = n - n;

これは本当ですか?もしそうなら、なぜそうなのですか?

編集:いくつかの返信で指摘されているように、コンパイラが同じものに最適化するのはかなり簡単だと思います。しかし、私が興味深いと思うのは、コンパイラが完全に一般的なアプローチを採用した場合に、なぜそれらが異なるのかということです。

4

9 に答える 9

11

よく使うアセンブラ コードの記述:

xor eax, eax

それ以外の

mov eax, 0

これは、最初のステートメントにはオペコードのみがあり、関連する引数がないためです。あなたのCPUはそれを(2ではなく)1サイクルで行います。あなたのケースは似ていると思います(サブを使用していますが)。

于 2009-05-15T09:31:31.653 に答える
7

コンパイラ VC++ 6.0、最適化なし:

4:        n = 0;
0040102F   mov         dword ptr [ebp-4],0
5:
6:        n = n - n;
00401036   mov         eax,dword ptr [ebp-4]
00401039   sub         eax,dword ptr [ebp-4]
0040103C   mov         dword ptr [ebp-4],eax
于 2009-05-15T09:31:24.463 に答える
6

最適化コンパイラは、この 2 つに対して同じアセンブリ コードを生成します。

于 2009-05-15T09:27:49.353 に答える
6

初期の頃は、メモリと CPU のサイクルが不足していました。これは、いわゆる「のぞき穴の最適化」の多くにつながります。コードを見てみましょう:

    move.l #0,d0

    moveq.l #0,d0

    sub.l a0,a0

最初の命令では、オペコードに 2 バイト、次に値 (0) に 4 バイトが必要です。つまり、4 バイトが無駄になり、メモリに 2 回アクセスする必要があります (オペコード用に 1 回、データ用に 1 回)。遅い。

moveq.lデータをオペコードにマージするため、より優れていましたが、0から7の間の値しかレジスタに書き込むことができませんでした. また、データ レジスタのみに制限されていたため、アドレス レジスタをすばやくクリアする方法はありませんでした。データレジスタをクリアしてから、データレジスタをアドレスレジスタにロードする必要があります(2つのオペコード。悪い)。

これは、任意のレジスタで機能する最後の操作につながり、1 回のメモリ読み取りで 2 バイトしか必要としません。Cに翻訳すると、次のようになります

n = n - n;

これは、最も頻繁に使用されるタイプn(整数またはポインター)で機能します。

于 2009-05-15T09:42:11.083 に答える
5

nが as として宣言されているかどうかによって異なりますvolatile

于 2009-05-15T09:28:09.337 に答える
4

レジスターをそれ自体から減算するか、それ自体と XOR することによってレジスターをゼロにするアセンブリ言語の手法は興味深いものですが、実際には C に変換されません。

最適化する C コンパイラは、理にかなっていればこの手法を使用しますが、明示的に書き出そうとしても、何も達成できない可能性があります。

于 2009-05-15T09:59:12.507 に答える
2

組み立てなどはよくわかりませんが、概ね、

n=0
n=n-n

n が浮動小数点の場合、常に等しいとは限りません。ここを参照して ください http://www.codinghorror.com/blog/archives/001266.html

于 2009-05-15T09:39:22.680 に答える