[英]Compiling assembly for X86/X64 for use with C#
我想将cpuid功能添加到我的C#应用程序中。 我在网上找到了这个有趣的博客文章。 我可能需要MASM进行编译,但是:
因此,任何帮助都将受到欢迎!
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.