quarta-feira, 23 de novembro de 2016

Using Intermediate Language Disassembler

Sometimes, with me very often, we do some “nonsense”. Some code analysis tool may help us. If you’re not very confident you could use Intermediate Language Disassembler or ildasm.exe. Here i present some little tips using Intermediate Language Disassembler. First make sure you have VS, and open vs native tools. With vs native tools open enter ildasm. Now we’ll make a basic program with C#.
 class Program  
   {  
     static void Main(string[] args)  
     {  
       Console.WriteLine("ok");  
     }  
   }  
Now you can build and after, open ildasm File > open and select your .exe and double click in main method, you will see this:
 .method private hidebysig static void Main(string[] args) cil managed  
 {  
  .entrypoint  
  // Code size    13 (0xd)  
  .maxstack 8  
  IL_0000: nop  
  IL_0001: ldstr   "ok"  
  IL_0006: call    void [mscorlib]System.Console::WriteLine(string)  
  IL_000b: nop  
  IL_000c: ret  
 } // end of method Program::Main  
So, no big deal, we have the string literal stored opcode following call to the WriteLine. Now we’ll do a potentially dangerous operation, we’ll write a method that expects an object, following we’ll pass a double. This will generate a box operation, so:
 class Program  
   {  
     static void Main(string[] args)  
     {  
       Console.WriteLine("ok");  
       double wrong = 2.3;  
       pass(wrong);  
     }  
     static void pass(Object wrong)  
     {  
       Console.WriteLine(wrong);  
     }  
   }  
Now we build and following we use ildasm:
 .method private hidebysig static void Main(string[] args) cil managed  
 {  
  .entrypoint  
  // Code size    35 (0x23)  
  .maxstack 1  
  .locals init ([0] float64 wrong)  
  IL_0000: nop  
  IL_0001: ldstr   "ok"  
  IL_0006: call    void [mscorlib]System.Console::WriteLine(string)  
  IL_000b: nop  
  IL_000c: ldc.r8   2.2999999999999998  
  IL_0015: stloc.0  
  IL_0016: ldloc.0  
  IL_0017: box    [mscorlib]System.Double  
  IL_001c: call    void Generics.Program::pass(object)  
  IL_0021: nop  
  IL_0022: ret  
 } // end of method Program::Main  
Now, we can see some nice things. First, we “discover” that our double is called float64, the 2.3 value(could not be different) is put as 2.2999999999999998 with the ldc.r8 opcode that pushes the value to the evaluation stack. Following we have our potentially Dracula: in the IL_0017 we have our box.
In MSDN:
In relation to simple assignments, boxing and unboxing are computationally expensive processes. When a value type is boxed, an entirely new object must be allocated and constructed. To a lesser degree, the cast required for unboxing is also expensive computationally. For more information, see Performance.

https://msdn.microsoft.com/en-us/library/yz2be5wk(v=vs.80).aspx

References:
https://msdn.microsoft.com/en-us/library/yz2be5wk(v=vs.80).aspx
https://app.pluralsight.com/library/courses/csharp-generics/table-of-contents

Nenhum comentário:

Postar um comentário