IA32架构CPUID、RDTSC指令与CPU测速

9 篇文章 0 订阅
4 篇文章 0 订阅
  • MD OL by Jimbowhy 2016/4/1 22:10:38

C语言程序代码:

/*********************************************************************\
    IA32 CPU Instructions demo by Jimbowhy 2016/4/1 18:10:28
    Compiler: Visual C++ 6, TDM-GCC 4.7.1

    CPUID Opcode [0F A2] CPU Identification
    The ID flag (bit 21) in the EFLAGS register indicates support for the CPUID instruction.
    CPUID returns processor identification and feature information in the EAX, EBX, ECX, and EDX registers.

    RDTSC Opcode [0F 31] Read time stamp counter
    Loads the current value of the processor's time-stamp counter,
    a 64-bit MSR into the EDX:EAX registers.

    RDTSCP Opcode [0F 01 F9] Read time stamp counter and processor ID
    Acts like what RDTSC will do, and also loads the IA32_TSC_AUX MSR 
    (address C000_0103H) into the ECX register.

    Text Out:
    CPU Information:
      CPU Frequency: 1570 MHZ
    CPU Manufacture: AuthenticAMD
           CPU Type: AMD Phenom(tm) II P920 Quad-Core Processor
\*********************************************************************/

#include <cstdio>
#include <cstring>
#include <ctime>

using namespace std;

void sleep( int ms )
{
    clock_t wait = clock() + ms * CLOCKS_PER_SEC / 1000;
    while (clock() < wait) { /* do nothing just waiting */ }
}

#ifdef _MSC_VER // for MSVC inline assembly

char * CPUID(unsigned int v)
{
    int r[4];
    __asm
    {
        mov eax,v
        cpuid
        mov r+0, eax
        mov r+4, ebx
        mov r+8, ecx
        mov r+12,edx
    }
    char *ret = new char[16];
    memcpy( ret, r, 16 );
    return ret;
}
/* tricky code
    int *r = new int[4]; access violated
    unsigned int r[4];
    __asm
    {
        mov eax,v
        cpuid
        mov r[0],eax  // mov    dword ptr [ebp-10h],eax
        mov r[1],ebx  // mov    dword ptr [ebp-0Fh],ebx
        mov r[2],ecx  // mov    dword ptr [ebp-0Eh],ecx
        mov r[3],edx  // mov    dword ptr [ebp-0Dh],edx
    }
*/

//@return frequency in MHz
int GetCPUFreq()
{
    int s,e;
    _asm rdtsc
    _asm mov s,eax
    sleep(50);
    _asm rdtsc
    _asm mov e,eax
    return (e-s)/50000;
}

#else // for GCC inline assembly
// asm ( "statements" : output_registers : input_registers : clobbered_registers);

char * CPUID(unsigned int v)
{
    unsigned int *r = new unsigned int[4];
    memset( r, 0, 4*sizeof(int) );
    __asm__ __volatile__(""::"a"(v) );
    asm("cpuid");
    asm __volatile__("":"=a"(r[0]), "=b"(r[1]), "=c"(r[2]), "=d"(r[3]) );
    return (char *) r;
}

int GetCPUFreq()
{
    int s, e;
    asm __volatile__( "rdtsc":"=a"(s) );
    sleep(50);
    asm __volatile__( "rdtsc":"=a"(e) );
    return (e-s)/50000;
}

#endif


//@return manufacture
char * GetManuID()
{
    char *id = new char[16];
    memset( id, 0, 16 );
    char *r = CPUID(0);
    memcpy( id+0, r+4,  4 );
    memcpy( id+4, r+12, 4 );
    memcpy( id+8, r+8,  4 );
    delete r;
    return id;
}

char * GetCPUType()
{
    unsigned int id = 0x80000002;
    char *type = new char[64];
    memset( type, 0, 64 );

    for(int t = 0 ; t < 3 ; t++ )
    {
        char *r = CPUID(id+t);
        memcpy( type + 16*t + 0, r+0, 4 );
        memcpy( type + 16*t + 4, r+4, 4 );
        memcpy( type + 16*t + 8, r+8, 4 );
        memcpy( type + 16*t +12, r+12,4 );
        delete r;
    }

    return type;
}

int main()
{
    printf("CPU Information: \n");
    printf("  CPU Frequency: %d%s\n", GetCPUFreq(), "MHz");
    printf("CPU Manufacture: %s\n",   GetManuID() );
    printf("       CPU Type: %s\n",   GetCPUType() );
    return 0;
}

自动化编译脚本NMAKE,Gnu Make 双版本:

#
#  Nmake makefile demo by Jimbowhy @ 2016/3/20 1:58:36
#  Usage:
#      nmake DEBUG=1 all
#      nmake all

CC=@cl -c /D "NDEBUG" /nologo -GX
CL=@link /nologo
MC=@mc.exe
RC=@rc.exe

CFLAGS=/I"C:\Program Files (x86)\Microsoft Visual Studio\VC98\Include"
LFLAGS=/LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio\VC98\lib"
libs=winmm.lib gdi32.lib user32.lib advapi32.lib kernel32.lib msimg32.lib

#CFLAGS=$(CFLAGS) /I"C:\sdks\PSDK2k3SP1\Include"
#LFLAGS=$(LFLAGS) /LIBPATH:"C:\sdks\PSDK2k3SP1\Lib" 

!IF "$(DEBUG)" == "1"
CC=@cl -c /ZI /Yd /MLd /Od /D "DEBUG" /nologo -c -GX
!ENDIF

all : cpuid

cpuid:
    $(CC) $(CFLAGS) -o cpuid cpuid.cpp
    $(CL) $(LFLAGS) cpuid.obj $(libs)

clean:
    del *.obj *.idb *.pdb *.res
#
#  GNU makefile demo by Jimbowhy @ 2016/3/18 14:56:39
#  Usage:
#       mingw32-make DEBUG=1 cpuid
#       mingw32-make all

MC=@mc.exe
RC=@windres.exe

CC=@g++
CFLAGS:=-s -O3
libs:=-lwinmm -lgdi32 -lkernel32 -lmsimg32

ifeq "DEBUG" "1"
CFLAGS:=-g
endif

ifeq "DYNAMIC" "1"
CFLAGS:=$(CFLAGS) -Wl,-Bdynamic
endif

CFLAGS:=$(CFLAGS) -I"." -L"C:\sdks\PSDK2k3SP1\Lib"


all : cpuid

cpuid:
    $(CC) $(CFLAGS) -o cpuid cpuid.cpp $(LFLAGS)

clean:
    del *.obj
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值