wenlong1423
7/13/2017 - 4:15 PM

ddddddd.cpp

#include <stdio.h>


#ifdef _WIN32
/* MSVC, x86-only. Stupid compiler doesn't allow __asm on x86_64. */
bool cpuid(unsigned *_eax, unsigned *_ebx, unsigned *_ecx, unsigned *_edx)
{
#ifdef TARGET_CPU_X86
	static bool cpuid_support = FALSE;

	if (!cpuid_support) {
		unsigned pre_change, post_change;
		const unsigned id_flag = 0x200000;

		/* This is pretty much the standard way to detect whether the CPUID
		 *     instruction is supported: try to change the ID bit in the EFLAGS
		 *     register.  If we can change it, then the CPUID instruction is
		 *     implemented.  */
		__asm {
			mov edx, id_flag;
			pushfd;                         /* Save %eflags to restore later.  */
			pushfd;                         /* Push second copy, for manipulation.  */
			pop ebx;                        /* Pop it into post_change.  */
			mov eax, ebx;                   /* Save copy in pre_change.   */
			xor ebx, edx;                   /* Tweak bit in post_change.  */
			push ebx;                       /* Push tweaked copy... */
			popfd;                          /* ... and pop it into eflags.  */
			pushfd;                         /* Did it change?  Push new %eflags... */
			pop ebx;                        /* ... and pop it into post_change.  */
			popfd;                          /* Restore original value.  */
			mov pre_change, eax;
			mov post_change, ebx;
		}

		if (((pre_change ^ post_change) & id_flag) == 0)
			return FALSE;
		else
			cpuid_support = TRUE;
	}
#endif

	__asm {
		mov esi, _eax;
		mov edi, _ecx;
		mov eax, DWORD PTR [esi];
		mov ecx, DWORD PTR [edi];
		cpuid;
		mov DWORD PTR [esi], eax;
		mov DWORD PTR [edi], ecx;
		mov esi, _ebx;
		mov edi, _edx;
		mov DWORD PTR [esi], ebx;
		mov DWORD PTR [edi], edx;
	}

	return true;
}
#else

bool cpuid(unsigned int *eax, unsigned int *ebx,
                                unsigned int *ecx, unsigned int *edx)
{
    asm volatile("cpuid"
        : "=a" (*eax),
          "=b" (*ebx),
          "=c" (*ecx),
          "=d" (*edx)
        : "0" (*eax), "2" (*ecx));
	return true;
}
#endif

int main(int argc, char **argv)
{
  unsigned eax, ebx = 0, ecx = 0, edx = 0;
  eax = 0x40000000; /* processor serial number */
  cpuid(&eax, &ebx, &ecx, &edx);

        char buf[13] = {0};
        *(unsigned *)(&buf[0]) = ebx;
        *(unsigned *)(&buf[4]) = ecx;
        *(unsigned *)(&buf[8]) = edx;

  printf("Hypervisor vendor string: %s\n", buf);

}