划分/移动装配差异

时间:2011-03-22 09:32:57

标签: c# assembly

早上好,下午或晚上,

关闭调试版本的汇编代码并关闭“抑制JIT优化(...)”选项后,我注意到以下奇怪行为(bitCountulong):< / p>

          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 % 32)而不是int BitRemainder = (int)(bitCount & 31)

00000120  mov         eax,dword ptr [ebp+8] 
00000123  mov         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] 
00000123  and         eax,1Fh 
00000126  mov         dword ptr [ebp-48h],eax 

非常感谢。

1 个答案:

答案 0 :(得分:3)

第一个代码段中的代码执行64位除法。 x86抖动不会为内联生成机器代码,会有太多的内存。它依赖于名为JIT_ULDiv的辅助函数。这是抖动或C编译器的常见策略。您可以在SSCLI20源代码clr / src / vm / jithelpers.cpp源代码文件中看到抖动可以使用的辅助函数类型。 long和ulong算术的辅助函数位于文件的顶部。

第二个片段进行32位除法,几乎不需要在线生成足够的机器码指令。将除法转换为班次是一种简单的优化。