2011-05-06 12 views
6

Estaba viendo esta pregunta: How to implement multiplication without using multiplication operator in .NET y de hecho me divertí mucho tratando de pensar en maneras de multiplicar sin usar *.¿Puede alguien explicarme este código?

Pero me quedé rascándome la cabeza con esta respuesta. No tengo idea de qué está pasando en este código.

¿Alguien me puede explicar esto?

using System; 
using System.Runtime.InteropServices; 

delegate uint BinaryOp(uint a, uint b); 

static class Program 
{ 
    [DllImport("kernel32.dll", SetLastError = true)] 
    static extern bool VirtualProtect(
     IntPtr address, IntPtr size, uint protect, out uint oldProtect); 

    static void Main() 
    { 
     var bytes = IntPtr.Size == sizeof(int) ? //32-bit? It's slower BTW 
      new byte[] {0x8B, 0x44, 0x24, 0x04, 0x0F, 0xAF, 0x44, 0x24, 0x08, 0xC3} 
     : new byte[] {0x0F, 0xAF, 0xCA, 0x8B, 0xC1, 0xC3}; 
     var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
     try 
     { 
      uint old; 
      VirtualProtect(handle.AddrOfPinnedObject(), 
       (IntPtr)bytes.Length, 0x40, out old); 
      var action = (BinaryOp)Marshal.GetDelegateForFunctionPointer(
       handle.AddrOfPinnedObject(), typeof(BinaryOp)); 
      var temp = action(3, 2); //6! 
     } 
     finally { handle.Free(); } 
    } 
} 

Crédito para este código va a Mehrdad.

Respuesta

12

Básicamente está creando un delegado del código nativo para la multiplicación, y luego invocando. Las matrices de bytes son las instrucciones en bruto, que luego se fijan en la memoria, se configuran para ser ejecutables, y luego Marshal.GetDelegateForFunctionPointer está creando el delegado.

El operador condicional es usar un código nativo diferente para x86 y x64. Sospecho que esto podría fallar cuando se ejecuta en Mono en un procesador ARM, por ejemplo :)

3

Este código contiene el binario de las instrucciones de la CPU. Encuentra la dirección del binario y lo ejecuta. Bastante horrible excepto como un ejemplo negativo o una broma.

1

Es el código de lenguaje ensamblador para implementar la multiplicación. La llamada para VirtualProtect es habilitar la ejecución del código en lo que de otro modo sería un segmento de datos no ejecutable.

+0

Código de máquina nativa en realidad, no lenguaje ensamblador. –

Cuestiones relacionadas