繁体   English   中英

用于C#的X86 / X64编译程序集

[英]Compiling assembly for X86/X64 for use with C#

我想将cpuid功能添加到我的C#应用​​程序中。 我在网上找到了这个有趣的博客文章。 我可能需要MASM进行编译,但是:

  1. 我应该如何开始?
  2. 我怀疑我将不得不为X86和X64都编译一个dll,但是我又不知道如何处理这样的事情(我有点时间紧迫)。

因此,任何帮助都将受到欢迎!

CPUID是一个巨大的痛苦,如果可以避免的话,我建议您不要沿着那条路走。 Intel和AMD处理器之间的CPUID结果有所不同(至少对于诸如超线程和缓存拓扑之类的有趣事物而言),并且在不同处理器版本之间并不是特别稳定。 (较新的Intel i7处理器引入了新的CPUID值(eax = 0xb),该值取代了较早处理器上CPUID支持的信息)。

如果可以解决,最好的选择是使用WMI(请参阅Win32_Processor )或GetLogicalProcessorInformation

如果它们在您的平台上受支持,那么这两种方法都将是一个极其简单且易于管理的解决方案(要获取逻辑处理器信息,无论哪种方式都需要在客户端使用WinXP sp3或更高版本,在服务器端需要Windows Server 2008或更高版本)。

如果您真的想尝试使用CPUID运气,我建议做的是创建一个简单的存根,该存根能够执行CPUID并将结果返回给托管代码(对于32位和64位,您将需要不同的版本)并在托管应用程序的上下文中执行这些操作。 我这样做是通过编译本机应用程序,然后将我的CPUID方法的原始指令字节提取到一个字节数组中,该数组可以从托管代码中执行。

这应该使您仅开始获得32位支持:

using System;
using System.Runtime.InteropServices;

static class Program {
  static void Main() {
    //Allocate the executable buffer on a distinct page 
    // rather than just pinning it in place because we
    // need to mark the page as executable.
    // Failing to do this would cause NX-enabled machines 
    // to have access violations attempting to execute.
    IntPtr pExecutableBuffer = VirtualAlloc(
      IntPtr.Zero,
      new IntPtr(CPUID_32.Length),
      AllocationType.MEM_COMMIT | AllocationType.MEM_RESERVE,
      MemoryProtection.PAGE_EXECUTE_READWRITE
    );

    Marshal.Copy(CPUID_32, 0, pExecutableBuffer, CPUID_32.Length);
    CPUID executeHandler = (CPUID)Marshal.GetDelegateForFunctionPointer(
      pExecutableBuffer, typeof(CPUID));
    CPUID_Args args = new CPUID_Args();
    args.eax = 0;
    executeHandler(ref args);
    Console.WriteLine("eax: {0} ebx: {1} ecx: {2} edx: {3}",
      args.eax,
      args.ebx,
      args.ecx,
      args.edx);
    VirtualFree(
      pExecutableBuffer,
      IntPtr.Zero,
      FreeType.MEM_RELEASE);
  }

  [UnmanagedFunctionPointer(CallingConvention.StdCall)]
  delegate void CPUID(ref CPUID_Args args);

  private static readonly byte[] CPUID_32 = new byte[] {
    0x53,          // push ebx 
    0x57,          // push edi 
    0x8B, 0x7C, 0x24, 0x0C, // mov edi,dword ptr [esp+0Ch] 
    0x8B, 0x07,       // mov eax,dword ptr [edi] 
    0x8B, 0x4F, 0x08,    // mov ecx,dword ptr [edi+8] 
    0x0F, 0xA2,       // cpuid      
    0x89, 0x07,       // mov dword ptr [edi],eax 
    0x89, 0x5F, 0x04,    // mov dword ptr [edi+4],ebx 
    0x89, 0x4F, 0x08 ,    // movdword ptr [edi+8],ecx 
    0x89, 0x57, 0x0C ,    // mov dword ptr [edi+0Ch],edx 
    0x5F,          // pop     edi 
    0x5B,          // pop     ebx 
    0xC2, 0x04, 0x00     // ret
    };

  [Flags]
  enum AllocationType {
    MEM_COMMIT = 0x1000,
    MEM_RESERVE = 0x2000,
  }

  [Flags]
  enum MemoryProtection {
    PAGE_EXECUTE_READWRITE = 0x40,
  }

  [Flags]
  enum FreeType {
    MEM_RELEASE = 0x8000
  }

  [DllImport("kernel32.dll")]
  static extern IntPtr VirtualAlloc(
    IntPtr lpAddress,
    IntPtr dwSize,
    AllocationType flAllocationType,
    MemoryProtection flProtect);

  [DllImport("kernel32.dll")]
  [return: MarshalAs(UnmanagedType.Bool)]
  static extern bool VirtualFree(
    IntPtr lpAddress,
    IntPtr dwSize,
    FreeType dwFreeType);
}

[StructLayout(LayoutKind.Sequential)]
struct CPUID_Args {
  public uint eax;
  public uint ebx;
  public uint ecx;
  public uint edx;
}

我认为您可以使用C ++代码中的内联汇编器语法( __asm )构建本机CLR汇编。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM