Ehs*_*jad 4 c# binary il byte ildasm
当我们声明一个变量时int,例如:
int i = 4;
Run Code Online (Sandbox Code Playgroud)
生成以下IL:
IL_0001: /* 1A | */ ldc.i4.4
Run Code Online (Sandbox Code Playgroud)
我可以理解1A是16的十六进制表示,所以我理解正确的十六进制值被保存用于指代它的值或它意味着不同的东西?
当我声明一个双变量时:
double d = 12.34;
Run Code Online (Sandbox Code Playgroud)
生成IL后,我无法得到一些东西:
IL_0003: /* 23 | AE47E17A14AE2840 */ ldc.r8 12.34
Run Code Online (Sandbox Code Playgroud)
23怎么样,它意味着什么,AE47E17A14AE2840这里有什么?
当我声明一个具有相同值的浮点数时:
float f = 12.34f;
Run Code Online (Sandbox Code Playgroud)
我现在有这个IL:
IL_000d: /* 22 | A4704541 */ ldc.r4 12.34
Run Code Online (Sandbox Code Playgroud)
同样的问题在这里是怎么22来的,它意味着什么,是A4704541什么?
我认为理解ildasm告诉你的是很重要的.管道字符前面的字节是操作码的值,后面的字节是操作数或参数.
我可以理解1A是16的十六进制表示,所以我理解正确的十六进制值被保存用于指代它的值或它意味着不同的东西?
1A在这种情况下是ldc.i4.4操作码的值.此操作码是ldc.i4 4指令的快捷方式,它将导致绝对相同的行为,但将是5个字节长,1个字节操作码和4个字节参数.这些快捷方式对于从-1到8的int值存在,因为它们经常被使用,因此可以减小方法体的大小.
现在应该清楚你的浮点指令是如何形成的.23并且22是操作码,参数是IEEE 754编码的浮点数.
不同的IL指令具有不同的字节代码.ldc.i4.4是0x1A,ldc.r8是0x23,ldc.r4是0x22.反编译器将这些字节值转换为相应的IL指令字符串,帮助您读取代码.
ldc.r4和ldc.r8指令有额外的字节来编码参数,分别是4字节浮点数和8字节双精度数.反编译器显示值的字节表示.A4-70-45-41与从BitConverter.GetBytes(12.34f)获得的字节数相同,只需在小程序中尝试即可查看.
ldc.i4.4指令有点特殊,它是一个推送4并且没有参数的专用指令.整数值-1到9有这样的指令,它们在程序中很常见.给他们专门的指令使IL紧凑.
“AE 47 E1 7A 14 AE 28 40”是 double 值的实际字节表示形式的十六进制表示形式12.34。
为了证明这一点
double d = 12.34;
var bytes = BitConverter.GetBytes(d);
StringBuilder sb = new StringBuilder();
foreach (var b in bytes)
{
sb.Append(b.ToString("X2"));
}
sb.Dump();
Run Code Online (Sandbox Code Playgroud)
印刷
AE47E17A14AE2840
Run Code Online (Sandbox Code Playgroud)
23 是操作码值的十六进制表示ldc.r8,22ldc.r4等。