2017-03-19 12 views
13

私はこのシンプルなプログラムを書いた後、Visual Studioで逆アセンブリモードに行ったとき、何か変わったことに気付きました。コンパイラは左に0ビットシフトする命令を追加しました。なぜコンパイラは0だけ左にシフトしますか?

なぜですか?これはargv[1]の評価に使用されること

... 
     return 0; 
00131C94 xor   eax,eax 
00131C96 jmp   main+57h (0131CC7h) 

    if (strcmp(argv[1], "-r") == 0) { 
00131C98 push  offset string "-r" (0138B30h) 
00131C9D mov   eax,4 
00131CA2 shl   eax,0 <------------------------- HERE 
00131CA5 mov   ecx,dword ptr [argv] 
00131CA8 mov   edx,dword ptr [ecx+eax] 
00131CAB push  edx 
00131CAC call  _strcmp (01313D9h) 
00131CB1 add   esp,8 
00131CB4 test  eax,eax 
00131CB6 jne   main+55h (0131CC5h) 
     printf("test"); 
00131CB8 push  offset string "test" (0138BD0h) 
00131CBD call  _printf (01313E8h) 
00131CC2 add   esp,4 
... 
+10

最適化を有効にしましたか? – Jester

+0

それは、x64ではなくx86に対してシフトを追加するように思えます。また、リリースビルドでは消えているようです。 – wally

答えて

12

注意:

#include <iostream> 

using namespace std; 

int main(int argc, char **argv) { 


    if (argc != 3) 
     return 0; 

    if (strcmp(argv[1], "-r") == 0) { 
     printf("test"); 
    } 

    return 0; 
} 

これはアセンブリコードである:

これは、C++コードです。

一般に、argv[N]は、コンパイラによって*((char**) ((char*) argv + N * sizeof *argv))に変換される必要があります。各ポインタは、次の後にsizeof *argvバイトです。 Nがコンパイル時にわからないときは、乗算がそこにある必要があり、shlがこれを行う通常の方法です。 N以来*

コンパイル時に知られていますが、最適化を有効にしていませんでした、私はこれはどうやらVisual Studioが何にこれを簡素化することが可能である

00131C9D mov   eax,1 
00131CA2 shl   eax,2 

にコンパイルします推測しているだろう最適化が無効になっていても最適化が行われていない場合でも、shlを完全に取り除くことはできません。この特定の場合において

*Nがコンパイル時に知られていない場合でも、shlが必要とされない:[ecx+eax*4]は、単一の命令でアクセスすることができます。これは、通常実行される別の最適化です。

+0

私はMSVCがフロントエンドでの強度低下を実行すると考えています。これはpccに基づいているので意味があります(IIRCも同様です)。 – fuz

関連する問題