gpt4 book ai didi

c# - 在c#中分配引用时添加神秘调用

转载 作者:太空狗 更新时间:2023-10-29 23:21:22 27 4
gpt4 key购买 nike

我知道其他人也写过类似的问题,但我认为我的情况不同,因为我找不到任何解决方案。

我有一个对象分配,像这样非常简单:

_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

恕我直言,它与垃圾收集有关,但我不明白它是什么,我真的很想弄清楚。我知道你们当中一定有人知道 :)

答案的附录,这是我从 CLR via C# 的 Google Books 中摘录的:

This is an extract I took from Google Books of the book: CLR via C#

最佳答案

我会对此稍加思考,一个完整的答案会填满一本书,让每个人都休眠。您对机器代码的看法非常不准确,32 位反汇编程序在转换 CALL 地址方面做得很差。如果您查看 64 位代码,这在最近的 VS 版本中有了很大改进,因为它不再伪造机器代码指令的地址。到达那里:

  • Project > Properties > Build 选项卡:Platform target = AnyCPU,取消勾选“Prefer 32-bit”
  • 项目 > 属性 > 调试选项卡:勾选“启用 native 代码调试”
  • 工具 > 选项 > 调试 > 符号:启用 Microsoft 符号服务器
  • 工具 > 选项 > 调试 > 常规:取消勾选“抑制 JIT 优化”。

仅当您想查看真实 机器代码时才需要最后的设置更改,即在您用户的机器上运行的那种。请注意,您现在正在查看未优化的调试代码。与此问题无关。

这很好地点亮了反汇编程序,尽管它仍然远非理想。 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。查看该代码需要一个额外的步骤,您必须强制调试器进入 native 模式。 Debug > Windows > Call Stack 并双击跟踪底部的 native 函数,如 RtlUserThreadStart。现在您可以将“07FFA7E3312B0”复制/粘贴到反汇编程序的地址框中,首先键入“0x”。我不会在这里展示它,这是手写的汇编代码,它做了一件相当神秘的事情,你永远无法从代码中进行逆向工程。

寻找这些抖动辅助函数的更好的地方是源代码,虽然它不是完全匹配,github CoreCLR project是你最好的选择。带你here .

通常,抖动会根据需要发出这些类型的直接 CLR 函数调用,它们的名称通常以“JIT”开头。这个恰好是用汇编语言编写的,但是并不常见;大多数是用 C++ 编写的。

关于c# - 在c#中分配引用时添加神秘调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34502858/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com