我知道其他人写了类似的问题,但我认为我的情况不同,因为我找不到任何解决方案。
我有一个对象赋值,这个非常简单:
_buffer3 = buffer; //they are just simple reference types
生成的汇编代码如下
mov edx,dword ptr [ebp-3Ch]
mov eax,dword ptr [ebp-40h]
lea edx,[edx+4]
call 69C322F0
现在,只是为了理解发生了什么,我想进入呼叫(为什么应该在分配中使用呼叫?)。但是该地址的代码不存在,我无法介入。 如果我在地址代码字段中输入地址,那就是显示的内容:
69C322F0 ???
试图解决这个问题的任何帮助? :)
编辑..显然,当在类的方法中分配引用时,会添加神秘的调用。
如果我有这门课程:
private class Test
{
int _X;
int _Y;
Test _t;
public void SetValues(int x, int y, Test t)
{
_X = x;
_Y = y;
}
}
为方法SetValues生成的程序集是:
_X = x;
00000028 mov eax,dword ptr [ebp-3Ch]
0000002b mov edx,dword ptr [ebp-40h]
0000002e mov dword ptr [eax+8],edx
_Y = y;
00000031 mov eax,dword ptr [ebp-3Ch]
00000034 mov edx,dword ptr [ebp+0Ch]
00000037 mov dword ptr [eax+0Ch],edx
这是有道理的
但是,如果我写这个
private class Test
{
int _X;
int _Y;
Test _t;
public void SetValues(int x, int y, Test t)
{
_X = x;
_Y = y;
_t = t;
}
}
神秘的电话出现
_X = x;
00000028 mov eax,dword ptr [ebp-3Ch]
0000002b mov edx,dword ptr [ebp-40h]
0000002e mov dword ptr [eax+8],edx
_Y = y;
00000031 mov eax,dword ptr [ebp-3Ch]
00000034 mov edx,dword ptr [ebp+0Ch]
00000037 mov dword ptr [eax+0Ch],edx
_t = t;
0000003a mov edx,dword ptr [ebp-3Ch]
0000003d mov eax,dword ptr [ebp+8]
00000040 lea edx,[edx+4]
00000043 call 515E2E48
恕我直言,它与垃圾收集有关,但我无法理解它是什么,我真的想弄明白。我知道有人必须知道:)
答案的附录,这是我通过C#从书籍CLR中获取的摘录:
答案 0 :(得分:4)
我会稍微谈谈这个问题,一个完整的答案会填满一本让每个人都入睡的书。您正在获得非常不准确的机器代码视图,32位反汇编程序在转换CALL地址方面做得很差。在最近的VS版本中,如果你查看64位代码,它已经有了相当大的改进,它不再伪造机器代码指令的地址。到达那里:
只有在您想要查看真实机器代码(用户机器上运行的那种)时,才需要进行最后一次设置更改。请注意,您现在正在查看未经优化的调试代码。与此问题无关。
尽管它仍然远非理想,但它很好地点亮了反汇编程序。 Test.SetValues()方法的尾端现在看起来像这样: _t = t;
00007FFA1ECB0C58 mov rdx,qword ptr [rbp+50h]
00007FFA1ECB0C5C lea rcx,[rdx+8]
00007FFA1ECB0C60 mov rdx,qword ptr [rbp+68h]
00007FFA1ECB0C64 call JIT_WriteBarrier (07FFA7E3312B0h)
显示的地址现在是准确的,0x07FFA7E3312B0。查看该代码需要一个额外的步骤,您必须强制调试器进入本机模式。调试> Windows>调用堆栈并双击跟踪底部的本机函数,如RtlUserThreadStart。现在,您可以将“07FFA7E3312B0”复制/粘贴到反汇编程序的“地址”框中,先键入“0x”。我不会在这里展示它,这是一个手写的汇编代码,它做了一个相当神秘的事情,你永远不能从代码中进行逆向工程。
查找这些抖动辅助函数的最佳位置是源代码,虽然它不完全匹配,github CoreCLR project是您最好的选择。带你here。
通常,抖动会根据需要发出这些直接CLR函数调用,它们的名称通常以“JIT”开头。这个碰巧是用汇编写的,但不是很常见;大多数是用C ++编写的。