2011-03-22 8 views
2

おはよう、午後または夜のシフト、分割手段/アセンブリの違いに

は、デバッグのアセンブリコードを見ていた「抑止JIT最適化(...)」でビルドオプションがオフになって、私は次のように奇妙なことに気づいています行動(bitCountulongある):

  int BitQuotient = (int)(bitCount/32); 

00000110 push  dword ptr [ebp+0Ch] 
00000113 push  dword ptr [ebp+8] 
00000116 push  0 
00000118 push  20h 
0000011a call  738EF4D5 
0000011f mov   dword ptr [ebp-44h],eax 

  int BitQuotient = (int)(bitCount >> 5); 

00000110 mov   eax,dword ptr [ebp+8] 
00000113 mov   edx,dword ptr [ebp+0Ch] 
00000116 shrd  eax,edx,5 
0000011a shr   edx,5 
0000011d mov   dword ptr [ebp-44h],eax 

とは対照的に、なぜアセンブリにおけるそのような違いがありますか?コンパイラは、32による除算が5で右へのシフトと同じで、コードを置き換えることを検出してはいけませんか?また、最初のコードではcall命令は何ですか?私はオペレータ/が非ネイティブのulongに適用されていることに関係していると思われますが、それはコンパイラがこの種の演算子をインライン化しないことを意味しますか?

編集:int BitRemainder = (int)(bitCount & 31)とは対照的に、int BitRemainder = (int)(bitCount % 32)を見てください:

00000120 mov   eax,dword ptr [ebp+8] 
0000mov   edx,dword ptr [ebp+0Ch] 
00000126 mov   ecx,20h 
0000012b cmp   edx,ecx 
0000012d jb   00000139 
0000012f mov   ebx,eax 
00000131 mov   eax,edx 
00000133 xor   edx,edx 
00000135 div   eax,ecx 
00000137 mov   eax,ebx 
00000139 div   eax,ecx 
0000013b mov   eax,edx 
0000013d xor   edx,edx 
0000013f mov   dword ptr [ebp-48h],eax 

00000120 mov   eax,dword ptr [ebp+8] 
0000and   eax,1Fh 
00000126 mov   dword ptr [ebp-48h],eax 

ありがとうございました。

+0

bitCountのデータタイプは? – jswolf19

+0

申し訳ありません... bitCountは 'ulong'です。 – Miguel

+0

ああ、私は話を始めようとしていました。あなたはそれを追加しました! –

答えて

3

最初のスニペットのコードは64ビットの除算を実行します。 x86ジッタは、そのインラインのマシンコードを生成しません。あまりにも多いでしょう。 JIT_ULDivというヘルパー関数に依存しています。これは、ジッタやそのためのCコンパイラの一般的な戦略です。ジッタがSSCLI20ソースコード、clr/src/vm/jithelpers.cppソースコードファイルで使用できるヘルパー関数の種類を見ることができます。 longおよびulong算術のヘルパー関数は、ファイルの先頭にあります。

第2のスニペットは32ビットの除算を行い、インラインで生成するのに十分なマシンコード命令を必要としません。分割をシフトに変換するのは単純な最適化です。