反汇编C#的一些很简单的代码,有些疑问,请大家帮忙释疑。随便写了一个数组有关的代码:int[] HistGram new
反汇编C#的一些很简单的代码,有些疑问,请大家帮忙释疑。
随便写了一个数组有关的代码:
int[] HistGram = new int[256];
HistGram[2]++;
然后设置一个断点,运行后,在断点哪一行点右键,反汇编,得到 HistGram[2]++这一行的汇编码 :
HistGram[2]++;
00000037 mov eax,dword ptr [ebp-0Ch]
0000003a cmp dword ptr [eax+4],2
0000003e ja 00000045
00000040 call 65247754
00000045 lea eax,[eax+10h]
00000048 mov dword ptr [ebp-14h],eax
0000004b mov eax,dword ptr [ebp-14h]
0000004e inc dword ptr [eax]
我先按照我的理解来解释下上面的几行代码:
mov eax,dword ptr [ebp-0Ch]
cmp dword ptr [eax+4],2 这两句应该是用来比较当前要使用的数组的索引是否大于数组的上标
ja 00000045 如果不大于,则跳转到00000045 行代码,否则call 65247754 应该是个异常抛出。
lea eax,[eax+10h] 设置eax寄存器的内容为HistGram[2]在内存中的地址
然后最后一句 inc dword ptr [eax] 就是将该地址中的内容++了。
因此,我就有2个问题了:
1: mov dword ptr [ebp-14h],eax
mov eax,dword ptr [ebp-14h]
这两句有什么用,如果说第一句有用,那也根本不需要第二句啊,有了第一句,那个内存中的内容和EAX的内容也就完全相同了嘛,还有,这两句似乎和我要执行的操作毫无关系啊。
2、如果我能完全确认我的代码访问数组的时候不会存在上下标越界的情况,在C#中有没有设置的选项让对应的汇编语言不产生这样的判断语句呢?因为我最关心的就是效率。
[解决办法]C#下标越界?你写一个出来给我看看。
下标越界检测和性能也没有一毛钱的关系。
计算机原理不清楚,搞来搞去,以为听说几个名词,其实一点用也没有。
[解决办法]1。
clrR的运算都是在evaluation stack上完成的,JIT生成本机代码可能没有那么智能,所以还是保留了保存和读取栈变量的指令,虽然这两句确实应该是没用的。
这段代码的IL是这样的:
.entrypoint
// Code size 33 (0x21)
.maxstack 3
.locals init ([0] int32[] HistGram)
IL_0000: nop
IL_0001: ldc.i4 0x100
IL_0006: newarr [mscorlib]System.Int32
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: ldc.i4.2
IL_000e: ldelema [mscorlib]System.Int32
IL_0013: dup
IL_0014: ldobj [mscorlib]System.Int32
IL_0019: ldc.i4.1
IL_001a: add
IL_001b: stobj [mscorlib]System.Int32
IL_0020: ret
这两个mov对应的应该是dup和ldobj
2。
取消边界检查:
unchecked
{
int[] HistGram = new int[256];
HistGram[2]++;
}
你可以看看这篇文章讲针对JIT优化代码
http://www.codeproject.com/Articles/25801/JIT-Optimizations
[解决办法]事实上CLR不是弱智,那只是调试版本的输出。
我特地跑了一下,在release版本(再次强调,这些代码只和我本机环境,当前CLR有关,因为这是JIT编译器产生的)机器代码是这样的:
...
002A0048 int 3
002A0049 push ss
002A004A and eax,dword ptr [eax]
002A004C xchg eax,esp
002A004D aaa
002A004E and eax,dword ptr [eax]
002A0050 push ebp
002A0051 mov ebp,esp
002A0053 mov ecx,68A04C8Ah
002A0058 mov edx,100h
002A005D call 00222214
002A0062 mov edx,eax
002A0064 cmp dword ptr [edx+4],2
002A0068 jbe 002A008B
002A006A lea eax,[edx+10h]
002A006D inc dword ptr [eax]
你可以看到那两条Mov指令都没有了。