发新话题
 搜藏 打印 该页面添加到 Mister Wong

用汇编检测CPU的主频

用汇编检测CPU的主频

如何检测CPU的主频


--------------------------------------------------------------------------------

概述:

    说到检测CPU的速度,一般是测试在单位时间内运算的指令条数,但用这种方法有太大的局限性,由于受到很多因素的影响,准确度比较低,特别是在Windows环境下,你不知道在你的程序外别的程序占用了多少的时间片。其实,在586及以上档次处理器中,已经有了一条专用的指令来测试主频,那就是 RDTSC指令,意思是读取时间标记计数器(Read Time-Stamp Counter),Time-stamp counter 是处理器内部的一个64位的MSR (model specific register),它每个时钟增加一个记数。在处理器复位的时候,初始值为0,RDTSC 指令把 TSC的值低32位装入EAX中,高32位装入EDX中。如果CPU的主频是200MHz,那么在一秒钟内,TSC的值增加 200,000,000 次。所以在计算的时候,把两次的TSC差值除以两次的时间差值就是CPU的主频。
    程序的结构如下: 初始化的时候设置一个定时器,定时时间为1秒,然后在定时器消息中利用 RDTSC 取得 TSC计数,再和上次保留的值相减,然后除以时间差即可。
    这里是本文中的所有的源程序。

源程序:



                .586
                .model flat, stdcall
                option casemap :none   ; case sensitive

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;        Include 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

include                windows.inc
include                user32.inc
include                kernel32.inc
include                comctl32.inc
include                comdlg32.inc

includelib        user32.lib
includelib        kernel32.lib
includelib        comctl32.lib
includelib        comdlg32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;        Equ 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

DLG_MAIN        equ                1000
ID_SPEED        equ                1001

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;        数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                .data?

dwTickCount        dd        ?
dwTSC                dd        ?,?
hInstance        dd        ?
szBuffer        db        256 dup        (?)

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;        子程序声明
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain        PROTO        :DWORD,:DWORD,:DWORD,:DWORD

                .data

szSpeed                db        "你的CPU主频为 %d MHz",0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;        代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                .code

include                Win.asm

;********************************************************************
_ProcDlgMain        proc        uses ebx edi esi, \
                hWnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD
                local        @stPoint:POINT
                local        @hWindow

                mov        eax,wMsg
                .if        eax == WM_CLOSE
                        invoke        EndDialog,hWnd,NULL
                        invoke        KillTimer,hWnd,1
                .elseif        eax == WM_INITDIALOG
                        invoke        _CenterWindow,hWnd
                        invoke        GetTickCount                ;TSC 初始值
                        mov        dwTickCount,eax

                        rdtsc
                        mov        dwTSC,eax
                        mov        dwTSC+4,edx
                        invoke        SetTimer,hWnd,1,1000,NULL
                .elseif        eax == WM_TIMER
                        invoke        GetTickCount
                        push        eax
                        sub        eax,dwTickCount
                        pop        dwTickCount
                        push        eax

                        rdtsc
                        push        edx
                        push        eax
                        sub        eax,dwTSC
                        sbb        edx,dwTSC+4
                        pop        dwTSC
                        pop        dwTSC+4

                        mov        ecx,1000000
                        div        ecx                        ;除以1Mhz=1000000hz
                        .if        edx >= 500000h                ;四舍五入
                                inc        eax
                        .endif
                        mov        ecx,1000
                        mul        ecx                        ;1秒=1000毫秒
                        pop        ecx                        ;pop出经过的毫秒数
                        div        ecx

                        invoke        wsprintf,offset szBuffer,offset szSpeed,eax
                        invoke        SendDlgItemMessage,hWnd,ID_SPEED,\
                                WM_SETTEXT,0,offset szBuffer
                .else
;********************************************************************
;        注意:对话框的消息处理后,要返回 TRUE,对没有处理的消息
;        要返回 FALSE
;********************************************************************
                        mov        eax,FALSE
                        ret
                .endif                  
                mov        eax,TRUE
                ret
               
_ProcDlgMain        endp
;********************************************************************
start:
                invoke        GetModuleHandle,NULL
                mov        hInstance,eax
                invoke        DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,0
                invoke        ExitProcess,NULL

                end        start

本文由GOD_Father 发布于Linuxsky 论坛,网址:http://bbs.linuxsky.org/thread-442-1-1.html

====================
夜,给了我黑色的眼睛;
我却用它来寻找光明,
寻找光明……

zyl508@163.com
====================

TOP

发新话题