seb*_*bas 5 c# assembly native-code
我知道其他人写了类似的问题,但我认为我的情况不同,因为我找不到任何解决方案.
我有一个对象赋值,这个非常简单:
_buffer3 = buffer; //they are just simple reference types
Run Code Online (Sandbox Code Playgroud)
生成的汇编代码如下
mov edx,dword ptr [ebp-3Ch]
mov eax,dword ptr [ebp-40h]
lea edx,[edx+4]
call 69C322F0
Run Code Online (Sandbox Code Playgroud)
现在,只是为了理解发生了什么,我想进入呼叫(为什么要在分配中使用呼叫?).但是,该地址的代码不存在,我无法介入.如果我在地址代码字段中键入地址,那就是显示的内容:
69C322F0 ???
Run Code Online (Sandbox Code Playgroud)
试图解决这个问题的任何帮助?:)
编辑..显然,当在类的方法内分配引用时,会添加神秘的调用.
如果我有这个课程:
private class Test
{
int _X;
int _Y;
Test _t;
public void SetValues(int x, int y, Test t)
{
_X = x;
_Y = y;
}
}
Run Code Online (Sandbox Code Playgroud)
为方法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
Run Code Online (Sandbox Code Playgroud)
这是有道理的
但是,如果我写这个
private class Test
{
int _X;
int _Y;
Test _t;
public void SetValues(int x, int y, Test t)
{
_X = x;
_Y = y;
_t = t;
}
}
Run Code Online (Sandbox Code Playgroud)
神秘的电话出现了
_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
Run Code Online (Sandbox Code Playgroud)
恕我直言,它与垃圾收集有关,但我无法理解它是什么,我真的想弄明白.我知道有人必须知道:)
答案的附录,这是我通过C#从书籍CLR中获取的摘录:
我会稍微讨论一下这个问题,一个完整的答案可以写满一本书,让每个人都入睡。您得到的机器代码视图非常不准确,32 位反汇编器在转换 CALL 地址方面做得非常糟糕。如果您查看 64 位代码,那么在最近的 VS 版本中,这一点已经有了很大的改进,它不再伪造机器代码指令的地址。到达那里:
仅当您想查看真实的机器代码(即在用户计算机上运行的代码)时,才需要更改最后的设置。请注意,您现在正在查看未优化的调试代码。与这个问题无关。
这很好地照亮了反汇编器,尽管它仍然远非理想。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)
Run Code Online (Sandbox Code Playgroud)
现在显示的地址是准确的,0x07FFA7E3312B0。查看该代码需要一个额外的步骤,您必须强制调试器进入本机模式。调试 > Windows > 调用堆栈,然后双击跟踪底部的本机函数,例如 RtlUserThreadStart。现在您可以将“07FFA7E3312B0”复制/粘贴到反汇编器的地址框中,首先输入“0x”。我不会在这里展示它,这是手写的汇编代码,它做了一件相当神秘的事情,你永远无法从代码中进行逆向工程。
寻找这些抖动辅助函数的更好位置是源代码,尽管它不完全匹配,但github CoreCLR 项目是您最好的选择。带你来这里。
一般来说,抖动会根据需要发出此类直接 CLR 函数调用,它们的名称通常以“JIT”开头。这个恰好是用汇编编写的,但并不常见;大多数是用 C++ 编写的。