假设我们有一个结构体数组Entry[2],它在内存中的布局如下所示:[hashcode(4byte),next(4byte),hashcode(4byte),next(4byte)]
\n\n [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 1)]\n struct Entry\n {\n [FieldOffset(0)]\n public int hashCode;\n [FieldOffset(4)]\n public int next;\n }\nRun Code Online (Sandbox Code Playgroud)\n\n所以现在我将在我的代码中访问此Entry[0].next
\n\nclass Test\n {\n Entry[] entries = new Entry[2];\n\n void AccessElement()\n {\n int n = entries[0].next; \n }\n }\nRun Code Online (Sandbox Code Playgroud)\n\n所以在AccessElement方法中,我只有一行代码,即:entries[0].next,我想知道CLR如何帮助我们访问这个元素。
\n我现在有两个想法,我将给你伪代码。
\n 1).idea 1
\n int n = (&entries+0)->next
\n 获取entries对象的地址,获取第一个元素(偏移量0),并访问下一个成员的值(相对于元素基地址的4字节)。
2).想法2
\n\nEntry entry = Copy(&entries[0],8);\nint n = entry.next;\nRun Code Online (Sandbox Code Playgroud)\n\n将条目对象的第一个元素(偏移量 0)复制到当前堆栈中,并返回当前堆栈对象条目的下一个成员
\n\n这两个想法是我对CLR访问结构体数组中元素成员的想法,这和我在某些情况下是否使用struct有关,毕竟大量数据mov有一些开销。所以有人可以告诉我吗CLR 如何访问结构体数组中元素成员的真实模式?调试和发布之间有什么区别吗?
\n\n谢谢
\n\n这是一个接收器代码。有人可以帮我读一下吗
\n\n Entry[] entries = new Entry[2];\n 00007FFB4B6D47F0 mov rcx,7FFB4B96361Ah\n 00007FFB4B6D47FA mov edx,2\n 00007FFB4B6D47FF call 00007FFBAA902630\n 00007FFB4B6D4804 mov qword ptr[rbp + 20h], rax\n 00007FFB4B6D4808 mov rax,qword ptr[rbp + 20h]\n 00007FFB4B6D480C mov qword ptr[rbp + 30h], rax\n int n = entries[1].next;\n 00007FFB4B6D4810 mov rax,qword ptr[rbp + 30h]\n 00007FFB4B6D4814 mov edx,1\n 00007FFB4B6D4819 cmp rdx,qword ptr[rax + 8]\n 00007FFB4B6D481D jb 00007FFB4B6D4824\n 00007FFB4B6D481F call 00007FFBAADA2660\n 00007FFB4B6D4824 lea rax,[rax+rdx*8+10h] \n 00007FFB4B6D4829 mov eax,dword ptr[rax + 4] \n 00007FFB4B6D482C mov dword ptr[rbp + 2Ch], eax\nRun Code Online (Sandbox Code Playgroud)\n\n也许我想太多了?我只是看了一下IL代码:
\n这是当Entry是引用类型时的IL
// Entry1[] entries = new Entry1[2];\n IL_0001 ldc.i4.2\n IL_0002 newarr ConsoleApp9.Entry1\n IL_0007 stloc.0\n // int n = entries[1].next;\n IL_0008 ldloc.0\n IL_0009 ldc.i4.1\n IL_000A ldelem.ref\n IL_000B ldfld System.Int32 ConsoleApp9.Entry1::next\n IL_0010 stloc.1\nRun Code Online (Sandbox Code Playgroud)\n\n如果 Entry 是结构类型,则这是 IL
\n\n // Entry[] entries = new Entry[2];\n IL_0001 ldc.i4.2\n IL_0002 newarr ConsoleApp9.Entry\n IL_0007 stloc.0\n // int n = entries[1].next;\n IL_0008 ldloc.0\n IL_0009 ldc.i4.1\n IL_000A ldelema ConsoleApp9.Entry\n IL_000F ldfld System.Int32 ConsoleApp9.Entry::next\n IL_0014 stloc.1\nRun Code Online (Sandbox Code Playgroud)\n\n对于结构化数组,指令为 ldelema \xef\xbc\x9a 将指定数组索引处的数组元素的地址作为 &(托管指针)类型加载到计算堆栈的顶部。
\n\n对于引用数组,指令为 ldelem.ref \xef\xbc\x9a 将指定数组索引处包含对象引用的元素作为 O 类型(对象引用)加载到计算堆栈的顶部。
\n\n那么真相大白了吗?
\n| 归档时间: |
|
| 查看次数: |
361 次 |
| 最近记录: |