sta*_*ica 7 .net cil reflection.emit endianness opcode
事实:
CIL指令rethrow的操作码的正确编码是双字节序列FE 1A.
OpCodes.Rethrow.Value(有类型short)0xFE1A在我的little-endian机器上有价值.
BitConverter 转换为/从字节序列转换时,尊重机器的字节顺序.
在我的little-endian机器上,BitConverter.GetBytes(OpCodes.Rethrow.Value)产生字节序列1A FE.
这意味着,OpCode.Value使用little-endian机器序列化BitConverter不会产生正确的操作码编码; 字节顺序颠倒过来.
问题:
记录的字节顺序OpCode.Value(如果是,在哪里?),还是"实现细节"?
上面的大端机器上的步骤4是否也会导致错误的字节排序?也就是说,将OpCodes.Rethrow.Value是0x1AFE一个big-endian的机器上?
我得出的结论是,根据OpCode.Value属性序列化操作码表示,即:
OpCode someOpCode = \xe2\x80\xa6;\nbyte[] someOpCodeEncoding = BitConverter.GetBytes(someOpCode.Value);\nRun Code Online (Sandbox Code Playgroud)\n\n是一个坏主意,但并不是因为使用了BitConverter.GetBytes(short),它的行为有详细记录。罪魁祸首是OpCode.Value财产,其文件在两个方面含糊不清:
它指出该属性包含“立即操作数的值”,它可能指也可能不指操作码的编码;该术语没有出现在 CLI 规范中的任何地方。
即使我们假设它实际上包含操作码的编码,文档也没有提及字节顺序。byte[](在和之间转换时,字节顺序会发挥作用short。)
为什么我的论点基于 MSDN 文档,而不是 CLI 标准?因为System.Reflection.Emit它不是 CLI 标准定义的反射库的一部分。因此,我认为可以相当肯定地说,该名称空间的 MSDN 参考文档与官方规范非常接近。(但与 @Hans Passant 的回答不同,我不会更进一步并声称参考源无论如何都是一种规范。)
结论:
\n\n有两种方法可以输出给定对象的操作码编码OpCode:
注重System.Reflection.Emit功能和使用ILGenerator.Emit(someOpCode)。在某些情况下这可能过于严格。
在操作码编码(即byte[]序列)和各种OpCode对象之间创建您自己的映射。