Yel*_*ika 33 c# il instructions
C#没有暴露哪些IL指令?
我指的是像sizeof和cpblk这样的指令 - 没有执行这些指令的类或命令(C#中的sizeof是在编译时计算的,而不是在运行时AFAIK计算的).
其他?
编辑:我问这个的原因(并希望这将使我的问题更有效)是因为我正在开发一个小型库,它将提供这些指令的功能.sizeof和cpblk已经实现 - 我想知道在继续之前我可能错过了什么.
编辑2:使用Eric的答案,我编写了一份说明列表:
列表中没有包含许多其他指令,我将它们分开,因为它们基本上是其他指令的快捷方式(压缩以节省时间和空间):
Eri*_*ert 36
我指的是像sizeof和cpblk这样的指令 - 没有执行这些指令的类或命令(C#中的sizeof是在编译时计算的,而不是在运行时AFAIK计算的).
这是不正确的.sizeof(int)
当然,它将被视为编译时常量4,但是有很多情况(所有unsafe
代码中)编译器依赖于运行时来确定结构的内存大小.例如,考虑一个包含两个指针的结构.它在32位机器上的大小为8,而在64位机器上为16.在这些情况下,编译器将生成sizeof操作码.
其他?
我没有我们没有生成的所有操作码的列表 - 我从来没有需要构建这样的列表.但是,我可以告诉你,在C#中无法生成"call indirect"(calli)指令; 我们偶尔会被要求提供该功能,因为它可以提高某些互操作方案的性能.
更新:我只是使用源代码来生成一个我们肯定会产生的操作码列表.他们是:
添加
add_ovf
add_ovf_un
和
arglist中
BEQ
beq_s
BGE
bge_s
bge_un
bge_un_s
BGT
bgt_s
bgt_un
bgt_un_s
BLE
ble_s
ble_un
ble_un_s
BLT
blt_s
blt_un
blt_un_s
bne_un
bne_un_s
盒
BR
br_s
brfalse
brfalse_s
brtrue
brtrue_s
调用
callvirt
castclass
CEQ
CGT
cgt_un
CLT
clt_un
约束
conv_i
conv_ovf_i
conv_ovf_i_un
conv_ovf_u
conv_ovf_u_un
conv_r
conv_r_un
conv_u
DIV
div_un
DUP
endfinally
initobj
isinst
ldarg
ldarg_
ldarg_s
ldarga
ldarga_s
ldc_i
ldc_r
ldelem
ldelem_i
ldelem_r
ldelem_ref
ldelem_u
ldelema
ldfld
ldflda
ldftn
ldind_i
ldind_r
ldind_ref
ldind_u
ldlen
ldloc
ldloc_
ldloc_s
ldloca
ldloca_s
ldnull
ldobj
ldsfld
ldsflda
ldstr
ldtoken
ldvirtftn
离开
leave_s
localloc
mkrefany
MUL
mul_ovf
mul_ovf_un
负
newarr
newobj
NOP
不
或
弹出
只读
refanytype
refanyval
REM
rem_un
保留
重新抛出
SHL
SHR
shr_un
的sizeof
starg
starg_s
stelem
stelem_i
stelem_r
stelem_ref
stfld
stind_i
stind_r
stind_ref
stloc
stloc_s
stobj
stsfld
子
sub_ovf
sub_ovf_un
开关
扔
unbox_any
挥发性
异或
我不会保证这一切都是他们所有人,但这肯定是他们中的大部分.然后,您可以将其与所有操作码的列表进行比较,并查看缺少的内容.
Shu*_*oUk 13
根据Eric的回答,这里有一些我发现的.在哪里我可以看到我指出它的原因,如果不是我自由推测.请随意指出这些推测是否错误.
Break
发信号通知公共语言基础结构(CLI)以通知调试器已触发断点.
您可以通过调用System.Diagnostics.Debugger.Break()来执行此操作,这似乎不直接使用该指令,而是使用烘焙到CLR中的BreakInternal()方法.
将指定数字字节从源地址复制到目标地址.将位于对象地址(类型&,*或native int)的值类型复制到目标对象的地址(类型&,*或native int).
我认为这些是为C++/CLI(以前的托管C++)添加的,但这纯粹是我的推测.它们也可能存在于某些系统调用中,但不会由编译器正常生成,并为不安全的乐趣和游戏提供一些范围.
将控制从异常的filter子句转移回公共语言基础结构(CLI)异常处理程序.
C#不支持异常过滤.VB编译器无疑会利用这一点.
将特定地址的指定内存块初始化为给定大小和初始值.
我将再次推测这在不安全的代码和C++/CLI中可能有用
退出当前方法并跳转到指定方法.
我将推测这种蹦床可能对那些想要避免尾调用的人有用.也许DLR利用它?
执行后缀方法调用指令,以便在执行实际调用指令之前删除当前方法的堆栈帧.
在其他地方深入讨论,目前c#编译器不会发出此操作码
指示当前在评估堆栈顶部的地址可能未与紧随其后的ldind,stind,ldfld,stfld,ldobj,stobj,initblk或cpblk指令的自然大小对齐.
C#(和CLR)对其产生的大部分代码和数据的对齐特性提出了相当多的保证.这不会被发射并不奇怪,但我可以看出为什么它会被包括在内.
将值类型的盒装表示形式转换为其未装箱的形式.
c#编译器更喜欢Unbox_Any
专门为此目的使用该指令.我认为,基于在2.0版本的指令集中添加它,它使得泛型要么可行,要么更简单.此时在整个代码中使用它来处理所有内容,泛型或其他内容,要么更安全,更简单,要么更快(或者是所有内容的某种组合).
脚注:
Prefix1,Prefix2,Prefix3,Prefix4,Prefix5,Prefix6,Prefix7,Prefixref
基础设施.这是保留的指令.
这些不是指令,有些IL指令比其他指令更长.这些可变长度的前缀应该从前缀开始,这些前缀本身永远不会有效,以使解析清晰.这些前缀操作码是为此保留的,因此它们不会在别处使用.毫无疑问,为IL序列实现基于switch语句的解析器的人会欣赏这些,因此他们可以捕获这些并保持状态.
归档时间: |
|
查看次数: |
2659 次 |
最近记录: |