2016-01-21 9 views
4

Когда мы объявляем переменную int, например:Как поплавок и двойная работа в IL

int i = 4; 

генерируется следующая IL:

IL_0001: /* 1A |     */ ldc.i4.4 

Я могу понять, что 1A является шестнадцатеричным представлением 4, так я понимаю, что значение шестнадцатеричного значения сохраняется, чтобы ссылаться на его ценность или что-то другое?

Когда я объявляю двойной переменной как:

double d = 12.34; 

Вслед за IL генерируется, который я не в состоянии получить несколько вещей в нем:

IL_0003: /* 23 | AE47E17A14AE2840 */ ldc.r8  12.34 

Как 23 идет и что это значит и что здесь AE47E17A14AE2840?

Когда я объявляю поплавок с тем же значением:

float f = 12.34f; 

у меня есть этот IL прямо сейчас:

IL_000d: /* 22 | A4704541   */ ldc.r4  12.34 

же вопрос здесь, а как 22 приходит и что это значит и что A4704541?

+0

Это только комментарии. Они вообще не влияют на двоичный файл. ваш дизассемблер генерирует их. – usr

ответ

8

Я думаю, что это имеет важное значение для понять, что говорит вам ildasm. Байтами перед символом канала являются значения кода операции, а следующие байты - это операнд или параметр.

Я могу понять, что 1A является шестнадцатеричным представлением 4, поэтому я понимаю, что значение шестнадцатеричного значения сохраняется, чтобы ссылаться на его значение или оно означает что-то другое?

1A В этом случае это значение кода операции ldc.i4.4. Этот код операции является ярлыком инструкции ldc.i4 4, которая приведет к абсолютному поведению, но будет иметь длину 5 байтов, 1 байтовый код операции и 4 байта. Эти ярлыки существуют для значений int от -1 до 8, потому что они часто используются, и поэтому размер тела метода может быть уменьшен.

Теперь должно быть ясно, как формируются ваши инструкции с плавающей запятой. 23 и 22 являются кодами операций, а параметр является номером с плавающей запятой IEEE 754.

7

Различные инструкции 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.

+0

оценил ваши слова –

3

«AE 47 E1 7A 14 AE 28 40» представляет собой шестнадцатеричное представление фактического представления байтов двойного значения 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(); 

Печать

AE47E17A14AE2840 

23 является шестнадцатеричное представление значения Opcode ldc.r8 и 22 для ldc.r4 и т.д.

Source

+0

спасибо, это помогло –