سؤال

أرغب في إضافة وظيفة CPUID إلى تطبيقي C #. وجدت هذه مثيرة للاهتمام مدونة آخر على الانترنت. ربما سأحتاج إلى ميزم لتجميع هذا ولكن:

  1. كيف يجب أن أبدأ؟
  2. أظن أنه سيتعين علي تجميع DLL لكلا x86 و x64 ولكن مرة أخرى ليس لدي أدنى فكرة عن كيفية الذهاب حول مثل هذا الشيء (وأنا مضغوط قليلا عن الوقت).

لذلك سيكون أي مساعدة أكثر من موضع ترحيب!

هل كانت مفيدة؟

المحلول

CPUID هو ألم عملاق وأود أن ينصح ضد النزول في هذا المسار إذا كنت تستطيع تجنب ذلك. تختلف نتائج CPUID بين معالجات Intel و AMD (على الأقل للأشياء المثيرة للاهتمام مثل طبولوجيا Hyperthreading وذاكرة التخزين المؤقت) وغير مستقرة بشكل خاص عبر إصدارات المعالج المختلفة. (تعرض معالجات 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;
}

نصائح أخرى

أعتقد أنه يمكنك إنشاء جمعية CLR الأصلية التي توظف بناء جملة المجمع المضمنة (__asm) في رمز C ++.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top