2009-04-23 37 views
4

在C#构造函数,即有通话结束长达this(...),实际调用被翻译成这样:需要一些帮助破译行的汇编代码,从.NET即时编译代码

0000003d call  dword ptr ds:[199B88E8h] 

什么DS注册内容在这里?我知道这是数据段,但这是通过VMT表还是类似的调用?我怀疑它,因为this(...)不会是一个虚拟方法的调用,只是另一个构造函数。

我问,因为该位置的值在某种程度上似乎很差,如果我按F11,在该调用指令中跟踪(Visual Studio 2008),该程序将因访问冲突而崩溃。

代码在第三方控制库内部,尽管我有源代码,但是我没有编译足够的调试信息的程序集,我只能通过反汇编程序跟踪它,然后我必须将其与实际代码进行匹配。

有问题的C#代码是这样的:

public AxisRangeData(AxisRange range) : this(range, range.Axis) { 
} 

反射显示我这个IL代码:

.maxstack 8 
L_0000: ldarg.0 
L_0001: ldarg.1 
L_0002: ldarg.1 
L_0003: callvirt instance class DevExpress.XtraCharts.AxisBase DevExpress.XtraCharts.AxisRange::get_Axis() 
L_0008: call instance void DevExpress.XtraCharts.Native.AxisRangeData::.ctor(class DevExpress.XtraCharts.ChartElement, class DevExpress.XtraCharts.AxisBase) 
L_000d: ret 

这是最后一次通话出现,同一类的其他构造,失败。调试器从不在其他方法内部展现,它只是崩溃。

为JITting后的方法拆卸是这样的:

00000000 push  ebp 
00000001 mov   ebp,esp 
00000003 sub   esp,14h 
00000006 mov   dword ptr [ebp-4],ecx 
00000009 mov   dword ptr [ebp-8],edx 
0000000c cmp   dword ptr ds:[18890E24h],0 
00000013 je   0000001A 
00000015 call  61843511 
0000001a mov   eax,dword ptr [ebp-4] 
0000001d mov   dword ptr [ebp-0Ch],eax 
00000020 mov   eax,dword ptr [ebp-8] 
00000023 mov   dword ptr [ebp-10h],eax 
00000026 mov   ecx,dword ptr [ebp-8] 
00000029 cmp   dword ptr [ecx],ecx 
0000002b call  dword ptr ds:[1889D0DCh] // range.Axis 
00000031 mov   dword ptr [ebp-14h],eax 
00000034 push  dword ptr [ebp-14h] 
00000037 mov   edx,dword ptr [ebp-10h] 
0000003a mov   ecx,dword ptr [ebp-0Ch] 
0000003d call  dword ptr ds:[199B88E8h] // this(range, range.Axis)? 
00000043 nop    
00000044 mov   esp,ebp 
00000046 pop   ebp 
00000047 ret    

基本上就是我要问的是:

  • 什么这里ds:[ADDR]间接的目的是什么? VMT表只是虚拟的不是吗?这是构造函数
  • 构造函数是否可以被打乱,这可能意味着调用实际上会通过JIT垫片调用?恐怕我在这里有深水,所以任何事情都可能会有帮助。

编辑:好了,问题只是变得更糟或更好,或什么的。

我们正在Visual Studio 2008解决方案中的C#项目中开发.NET特性,并通过Visual Studio进行调试和开发。

但是,最终,这些代码将被加载到由Win32 Delphi应用程序托管的.NET运行时。我们也可以配置Visual Studio项目/解决方案/调试器,将生成的dll复制到Delphi应用程序的目录,然后通过Visual Studio调试器执行Delphi应用程序。为了便于实验这些功能,我们还可以配置Visual Studio项目/解决方案/调试器。

原来,如果我在调试器外运行程序,但在调试过程中每次都会出现问题,问题就会消失。

不确定是否有帮助,但由于该代码未在6个月左右的时间内发布,因此我们很快就会对测试版本带来一些压力。

我会在稍后深入研究记忆部分,但可能不会在周末之前完成,然后发布后续内容。

+0

你能找出ds:[199B88E8h]实际指向哪个地址并拆卸它吗? – Groo 2009-04-23 14:18:48

+0

这是存储在该地点的地址,该地址指向未映射的内存,因此存在访问冲突。 – 2009-04-24 07:37:48

回答

3

数据段是编译器通常将全局变量放入导入地址表所在的位置。

00000029 cmp   dword ptr [ecx],ecx 
0000002b call  dword ptr ds:[1889D0DCh] 

第一行实际上是一个空检查,最终提出了一个NullReferenceException如果位于ECX寄存器的指针是无效的。

callvirt MSIL指令必须在调用实际方法之前执行空值检查。话虽这么说,我们可以安全地假设的汇编代码这两行具有以下MSIL代码表示:

class DevExpress.XtraCharts.AxisBase DevExpress.XtraCharts.AxisRange::get_Axis() 

而且评论汇编代码:

00000026 mov   ecx,dword ptr [ebp-8]  // store the pointer to the 'range' in ECX 
00000029 cmp   dword ptr [ecx],ecx  // null-check 
0000002b call  dword ptr ds:[1889D0DCh] // range.get_Axis() 
00000031 mov   dword ptr [ebp-14h],eax // store the result in a local variable 
00000034 push  dword ptr [ebp-14h]  // push the result onto a stack 
00000037 mov   edx,dword ptr [ebp-10h] // this variable was previously loaded with the 'range' pointer 
0000003a mov   ecx,dword ptr [ebp-0Ch] // here seems to be stored the actual 'this' pointer 
0000003d call  dword ptr ds:[199B88E8h] // call the this(...) ctor 

这是我不清楚为什么它的崩溃,你有没有试过查找内存位置的内容(DS:[199B88E8h])?