首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 汇编语言 >

反汇编C#的一些很简单的代码,有点疑问,请大家帮忙释疑

2012-12-23 
反汇编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

[解决办法]
引用:
1。
clrR的运算都是在evaluation stack上完成的,JIT生成本机代码可能没有那么智能,所以还是保留了保存和读取栈变量的指令,虽然这两句确实应该是没用的。
这段代码的IL是这样的:
Plain Text code?1234567891011121314151617  .entrypoint  // Code size       33 (0x21) ……


事实上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指令都没有了。

热点排行