Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 什么被认为是;自然线形“;操作码。Ldobj?_C#_Alignment_Cil_Opcode - Fatal编程技术网

C# 什么被认为是;自然线形“;操作码。Ldobj?

C# 什么被认为是;自然线形“;操作码。Ldobj?,c#,alignment,cil,opcode,C#,Alignment,Cil,Opcode,我正在玩“Reflection.Emit”,希望生成一个静态类,该类在C#中公开一个具有此签名的方法: 我希望这些方法能产生如下结果: { // CopyDef ldarg.0 ldarg.1 ldobj Def stobj Def ret } { // CopySeq ldarg.0 ldarg.1 unaligned. 1 ldobj Seq unaligned. 1 stobj Seq ret } 相

我正在玩“Reflection.Emit”,希望生成一个静态类,该类在C#中公开一个具有此签名的方法:

我希望这些方法能产生如下结果:

{ // CopyDef
  ldarg.0
  ldarg.1
  ldobj      Def
  stobj      Def
  ret
}
{ // CopySeq
  ldarg.0
  ldarg.1
  unaligned. 1
  ldobj      Seq
  unaligned. 1
  stobj      Seq
  ret
}
相反,Seq的输出与Def相同,即没有未对齐的x操作码。我希望ldobj/stobj将除自然机器对齐(例如8/4)之外的任何内容都视为未对齐,但我显然错了

我的问题和后续问题:

由于ldobj/stobj操作码必须指定其操作的地址类型,因此“Pack=1”是否以某种方式隐式地“注意到”

如果是这种情况,这是否意味着只要地址不引用小于4的偏移量(例如2,1),带有“Pack=4”的结构就被隐式“处理”,在这种情况下,操作码前面必须有未对齐的x?当然,这只会在初始方法签名中使用非托管指针时发生

更新:

从Opcode.Ldind_I4 MSDN(1)中:

所有ldind指令都是指定相应内置值类的Ldobj指令的快捷方式

来自操作码。未对齐的MSDN(2):

未对齐指定地址。。。堆栈上的数据可能与紧随其后的ldind、stind、。。。ldobj,stobj。。。指示也就是说,对于Ldind_I4指令,地址的对齐可能不是4字节边界

来自操作码Ldobj MSDN(3):

复制的字节数取决于类的大小(由class参数指定)。类参数是表示值类型的元数据标记

从Opcode.Ldind_I4 MSDN(4)中:

返回地址(例如,Ldloca和Ldarga)的所有MSIL指令的结果都是安全对齐的

这表明:

  • “Ldind_I4”=“Ldobj Int32”
  • 4字节int上的Ldobj将4字节偏移量视为对齐
  • Ldobj“知道”它所操作的类型的大小
  • Ldelema无法生成未对齐的地址
  • 任何可blittable结构的数组中可能出现的最差(最低)偏移量为:

    int offset = sizeof(myStruct) & 7; // 3 for 32bit
    // offset == 0     -> correct
    // offset == 1,3,7 -> unaligned. 1
    // offset == 2,6   -> unaligned. 2
    // offset == 4     -> unaligned. 4
    
    Seq的大小是9,这给了我们7的偏移量,这意味着我们(最坏的情况)未对齐1

    以下CopySeq方法不会生成未对齐的操作码

    static void CopySeq(ref Seq dest, Seq[] src) { dest = src[1]; }
    
    { // CopySeq
        ldarg.0
        ldarg.1
        ldc.i4.1
        ldelema    Seq
        ldobj      Seq
        stobj      Seq
        ret
    }
    

    除非ldelema对后续的ldobj施展了魔法,否则ldobj应该知道如何处理指定类型的数组中可能出现的任何未对齐,这可以由该类型的大小确定。

    结构没有未对齐。结构中的某个字段可能未对齐并不重要。@HansPassant如果结构位于seqArr[1]的数组中,它会不会未对齐,因为sizeof(Seq)是9,第二项将直接位于其后?您不使用ldobj直接加载数组元素,而是使用ldelema。@HansPassant我知道ldelema。我想说的是,CopySeq的调用方可以传递seqArr[]的两个任意索引中的两个项。这两个项目中的任何一个都可能未对齐,甚至有不同的偏移。这不是真的吗?
    int offset = sizeof(myStruct) & 7; // 3 for 32bit
    // offset == 0     -> correct
    // offset == 1,3,7 -> unaligned. 1
    // offset == 2,6   -> unaligned. 2
    // offset == 4     -> unaligned. 4
    
    static void CopySeq(ref Seq dest, Seq[] src) { dest = src[1]; }
    
    { // CopySeq
        ldarg.0
        ldarg.1
        ldc.i4.1
        ldelema    Seq
        ldobj      Seq
        stobj      Seq
        ret
    }