我正在看这个问题:How to implement multiplication without using multiplication operator in .NET并且在尝试考虑如何在不使用*的情况下成倍增长时实际上有很多乐趣。
但是我对这个答案感到很头疼。我不知道这段代码发生了什么。
有人可以向我解释一下吗?
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(); }
}
}
此代码可归功于Mehrdad。
答案 0 :(得分:12)
它基本上是从 native 代码创建一个委托进行乘法,然后调用它。字节数组是原始指令,然后固定在内存中,设置为可执行,然后Marshal.GetDelegateForFunctionPointer
创建委托本身。
条件运算符是为x86和x64使用不同的本机代码。我怀疑在ARM处理器上运行Mono时会失败,例如:)
答案 1 :(得分:3)
此代码包含CPU指令的二进制文件。它找到二进制文件的地址并执行它。非常糟糕,除非作为反面例子或笑话。
答案 2 :(得分:1)
实现乘法是汇编语言代码。对VirtualProtect
的调用是为了在其他非可执行数据段中执行代码。