【发布时间】:2019-07-23 22:40:33
【问题描述】:
似乎无法为这些问题找到一个好的答案。
以下是我认为我知道的和我不清楚的。
- 评估堆栈是类似于 C 样式堆栈的内存缓冲区(它是原生 int / size_t 的堆栈)吗?
- 评估堆栈元素可以是 32 位或 64 位(这些元素如何混合在一个堆栈中?)
- Ldloc_0 将局部变量存储在评估堆栈上,但是如果它大于 64 位怎么办?
- Ldloc_0 是否只是将 ptrs 存储到评估堆栈上的局部变量中?
- 评估堆栈中存储的对象是否总是指针或原始值?
- 如果 .maxsize 为 8 是否意味着 (8 * size_t)?如果是这样,如果我阅读说明其 32 位或 64 位的文档,该怎么办
以下面的例子为例。此局部变量是否通过 ptr 引用存储在评估堆栈中?
public struct MyStruct
{
public long x, y, z;
public static MyStruct Foo()
{
MyStruct c;
c.x = 1;
c.y = 2;
c.z = 3;
return c;
}
}
“ldloc.0”清楚地将结构存储到评估堆栈中,但它也远大于 64 位。是否存储了引用?
.class public sequential ansi sealed beforefieldinit MyStruct
extends [mscorlib]System.ValueType
{
// Fields
.field public int64 x
.field public int64 y
.field public int64 z
// Methods
.method public hidebysig static
valuetype MyStruct Foo () cil managed
{
// Method begins at RVA 0x2050
// Code size 34 (0x22)
.maxstack 2
.locals init (
[0] valuetype MyStruct,
[1] valuetype MyStruct
)
IL_0000: nop
IL_0001: ldloca.s 0
IL_0003: ldc.i4.1
IL_0004: conv.i8
IL_0005: stfld int64 MyStruct::x
IL_000a: ldloca.s 0
IL_000c: ldc.i4.2
IL_000d: conv.i8
IL_000e: stfld int64 MyStruct::y
IL_0013: ldloca.s 0
IL_0015: ldc.i4.3
IL_0016: conv.i8
IL_0017: stfld int64 MyStruct::z
IL_001c: ldloc.0// What is actually stored here?
IL_001d: stloc.1
IL_001e: br.s IL_0020
IL_0020: ldloc.1
IL_0021: ret
} // end of method MyStruct::Foo
} // end of class MyStruct
【问题讨论】:
-
不要忘记评估堆栈是抽象的。 CIL 是 JITted,所以当代码实际执行时,值可能会存储在寄存器或内存位置。
-
@llidanS4 明白了。制作一个 IL 到 C 的翻译器并只向前分支预测将设置哪些本地或字段变量,然后修改“Br”/goto 位置。这样我就得到了 C 级优化。
标签: .net stack evaluation cil