C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[6179] [급질문]CYRIX CPU 정보 알아내는 소스인데 ASM으로 된 함수를 참조 하는 방법 좀 가르쳐주세여.
허접푸케케 [] 2257 읽음    2001-03-19 11:06
데브피아에서.. CYRIX CPU 정보 알아내는 소스를 구했는데여....
C와 asm 으로 되어있는데...asm으로 된 함수를 콜하는 부분이 있는데..
Cbuilder에서 어떻게 사용해야 하나여...
넘 초보라.....어찌 해야할지 모르겠네여...
넘 개념없는 질문이라....고생스럽더라도...ㅠ.ㅠ

/* ..................................................................... */
/* includes                                                              */
/* ..................................................................... */
#include <string.h>
#include "cyrix.h"
#include "cpu_type.h"
#include "cpu_mhz.h"

/* ..................................................................... */
/* implemention functions prototypes                                     */
/* ..................................................................... */

/* Used for cpu_type */
#define Cx486        0x1  
#define _5x86        0x2
#define MediaGX      0x3
#define _6x86        0x4
#define _6x86MX      0x5


/* .ASM functions used */
int isfpu (void);
int iscyrixfpu (void);
int is_cpuid_supported (void);
int oldiscyrix (void);
int is486(void);
int isv86(void);
char cx_r (char);
void cx_w (char, char);
unsigned long cpu_speed( unsigned int );
void read_time_stamp( unsigned long *v1, unsigned long *v2 );
void get_cpuid_info (long v1, long *v2, long *v3, long *v4, long *v5);


/* functions used internally only */
static unsigned short Get_DIRs(char *, char *);
static void NameByDIRs (unsigned char, unsigned char, char* );
static void Set_Features(unsigned char, unsigned char, CPUInfo* );
static int cpu_type(void);




//Cyrixasm.asm 파일-------------------------------------------------------------------------public _is_cpuid_supported
public _get_cpuid_info
public _extended_cpuid_supported
public _oldiscyrix
public _iscyrixfpu
public _is486
public _isfpu
public _isv86
public _cx_r
public _cx_w
public _read_time_stamp
public _cpu_speed

assume  cs:_TEXT

rdtsc macro
        db 0fh, 031h
endm

_TEXT   segment byte public 'CODE'

;**************************************************************************   
;       Function:    int is_cpuid_supported ()
;
;       Purpose:        Check for existence of CPUID instruction.
;                       If exists execute CPUID with eax==0.
;
;       Inputs:         none
;                      
;       Output:        
;                      
;       Returns:        0 - no CPUID instruction supported
;                       1 - CPUID instruction supported
;**************************************************************************

cpuid macro
        db 0fh, 0a2h
endm

_is_cpuid_supported        proc    near
.386
        pushfd                  ; save current flags
        push    eax
        push    ebx

        pushfd                  ; get extended flags
        pop     eax
        mov     ebx, eax        ; save current flags

        xor     eax, 200000h    ; toggle bit 21
        push    eax             ; put new flags on stack
        popfd                   ; flags updated now in flags

        pushfd                  ; get extended flags
        pop     eax            
        xor     eax, ebx        ; if bit 21 r/w then eax <> 0

        pop     ebx
        pop     eax

        je      no_cpuid        ; can't toggle id bit (21) no cpuid here

        mov     eax, 1          ; cpuid supported

        jmp     done_cpuid_sup

no_cpuid:
        mov     eax, 0          ; cpuid not supported

done_cpuid_sup:
        popfd                   ; restore original flags
    ret
_is_cpuid_supported        endp

;**************************************************************************   
;       Function:       void get_cpuid_info (long level,
;                                            long ®_eax,
;                                            long ®_ebx,
;                                            long ®_ecx,
;                                            long ®_edx)
;
;       Purpose:        Execute CPUID instruction at level (eax==level)
;
;       Inputs:         level - eax value when CPU is executed
;                      
;       Output:         reg_eax - eax after executing CPUID
;                       reg_ebx - ebx after executing CPUID
;                       reg_ecx - ecx after executing CPUID
;                       reg_edx - edx after executing CPUID
;**************************************************************************
_get_cpuid_info        proc    near
.386
    push    bp
    mov    bp, sp

        push    eax
        push    ebx
        push    ecx
        push    edx
        push    esi

    mov    eax, dword ptr [bp+4]      ; get level

        cpuid                  

    mov    si,word ptr [bp+8]
    mov    dword ptr [si],eax        ; reg_eax := eax

    mov    si,word ptr [bp+10]
    mov    dword ptr [si],ebx        ; reg_ebx := ebx

        mov    si,word ptr [bp+12]       ; reg_ecx := ecx
    mov    dword ptr [si],ecx

        mov    si,word ptr [bp+14]       ; reg_edx := edx
    mov    dword ptr [si],edx

        pop     esi
        pop     edx
        pop     ecx
        pop     ebx
        pop     eax

        mov     sp,bp
        pop     bp
    ret
_get_cpuid_info        endp


;**************************************************************************   
;       Function:       int extended_cpuid_supported
;
;       Purpose:        Determine if ExtendedCPUID is supported
;       Technique:      Do CPUID with eax = 8000 0000, if eax returns a
;                        value greater than 1, then it is supported
;       Inputs:         none
;       Output:         ax == 1 ExtendedCPUID supported, 0 if not
;**************************************************************************

_extended_cpuid_supported       proc near

.386
        mov     eax, 80000000h  ; try extended CPUID
        cpuid                  

        cmp     eax, 1          ; eax > 1
        jle     no_ecpuid

        mov     eax, 1          ; extended cpuid supported
        jmp     done_ecpuid

no_ecpuid:
        mov     eax, 0          ; extended cpuid not supported

done_ecpuid:
    ret
_extended_cpuid_supported        endp


;**************************************************************************   
;       Function:       int oldiscyrix ()
;
;       Purpose:        Determine if Cyrix CPU is present via 5/2 method
;       Technique:      Cyrix CPUs do not change flags where flags change
;                        in an undefined manner on other CPUs
;       Inputs:         none
;       Output:         ax == 1 Cyrix present, 0 if not
;**************************************************************************
_oldiscyrix   proc near
        push  bx
        xor   ax, ax         ; clear ax
        sahf                 ; clear flags, bit 1 is always 1 in flags
        mov   ax, 5         
        mov   bx, 2
        div   bl             ; do an operation that does not change flags
        lahf                 ; get flags
        cmp   ah, 2          ; check for change in flags
        jne   not_cyrix1     ; flags changed not Cyrix       
        mov   ax, 1          ; TRUE Cyrix CPU
        jmp   done1

not_cyrix1:
        mov  ax, 0           ; FALSE NON-Cyrix CPU
done1:
        pop  bx
        ret
_oldiscyrix   endp

;**************************************************************************   
;       Function:       int iscyrixfpu()   
;       Technique:
;               On both the Cyrix and Intel math coprocessor the function
;               2^x-1 is undefined when its argument does not lie between
;               -1 and +1. Therefore, when this function is evaluated at
;               x=pi it is not surprising that the answers returned by the
;               Cyrix and Intel chips are distinct.  This program computes
;               2^PI-1 and stores the result as a single precision number
;               VALUE.  It is possible to distinguish between the Cyrix and
;               Intel math coprocessors by comparing VALUE with the known
;               value obtained when using a Cyrix or Intel math coprocessor.
;
;       Purpose:        Determine if Cyrix FPU is present
;       Inputs:         None
;       Output:         AX=1 if Cyrix FPU Present else AX=0
;**************************************************************************

_iscyrixfpu    proc    near
    push    bp
    mov    bp,sp
    sub    sp,4                    ; get stack space
    push    si                      ; use as temp

    finit                            ; inialize fpu
    fldpi                            ; fpu loads pi
    f2xm1                            ; 2^pi - 1
    fstp    dword ptr [bp-4]        ; store computed value

    lea    si, word ptr [bp-2]     ; get address of stored value
    cmp    word ptr [si], 3FC9h    ; compare stored value to Cyrix
        jne     short not_cyrix2
    mov    ax, 1                   ; True Cyrix FPU present
        jmp     short done2

not_cyrix2:
    mov    ax, 0                   ; FALSE Cyrix FPU not present

done2:
    pop    si
    mov    sp,bp
    pop    bp
    ret   
_iscyrixfpu    endp

;**************************************************************************   
;       Function:    is486 ()
;
;       Purpose:        Check for presence of a 486 level support.
;
;       Returns:        1 if 486 or better present.
;                       0 if earlier than a 486 is present.
;                      
;**************************************************************************

_is486  proc near

        .486
    pushfd            ; save EFLAGS

    pop    eax        ; get EFLAGS
    mov    ecx, eax    ; temp storage EFLAGS
    xor    eax, 1 SHL 18    ; change AC bit in EFLAGS
       
    push    eax        ; put new EFLAGS value on stack
    popfd            ; replace current EFLAGS value

    pushfd            ; get EFLAGS
    pop    eax        ; save new EFLAGS in EAX
    cmp    eax, ecx    ; compare temp and new EFLAGS

        jz      is_not_80486
    mov    ax, 1            ; 80486 present
        jmp     done3

is_not_80486:       
        mov     ax, 0           ; 80486 not present

done3:
    push    ecx             ; get original EFLAGS
    popfd            ; restore EFLAGS
        ret

_is486  endp

;**************************************************************************   
;       Function:    isfpu ()
;
;       Purpose:        Determine if FPU is present
;       Inputs:         None
;       Output:         ax=1 if FPU present, 0 otherwise
;**************************************************************************
_isfpu proc near
        .386
        .387
        fninit
        mov     ax, 5a5ah
        fnstsw  ax
        cmp     ax, 0
        jne     no_fpu
        mov     ax, 1
        jmp     done4

no_fpu:       
        mov     ax, 0
done4:
        ret

_isfpu  endp

;**************************************************************************   
;       Function:    isv86()
;
;       Purpose:        Determine if CPU is in REAL or V86
;       Technique:      Check PE bit.  If set then assume V86.
;                       *** Note ***  This technique only works
;                                     for distinguishing V86 vs REAL.
;                                     IT does not hold for anything else!
;       Inputs:         none
;       Output:         ax == 1 in V86 mode, else 0
;**************************************************************************

_isv86 proc near
        .486P
        smsw    ax
        test    al, 1
        jz      no_v86
        mov     ax, 1
        jmp     done5

no_v86:       
        mov     ax, 0
done5:
        ret

_isv86  endp

;**************************************************************************   
;       Function:    char cx_r (char index)
;
;       Purpose:        Reads Cyrix Configuration Register at index
;       Inputs:         byte index, Cyrix Configuration Register
;       Output:         al, Contents of Cyrix Configuration Register
;**************************************************************************
_cx_r    proc    near
    push    bp
    mov    bp,sp
        pushf                           ; save flags
        cli                             ; clear interrupt in flags
    mov    al, byte ptr [bp+4]     ; get index
    out    22h, al                 ; tell CPU which config. register
    in    al, 23h                 ; write to CPU config. register
        popf                            ; restore flags
    mov    sp,bp
    pop    bp
    ret   
_cx_r    endp

;**************************************************************************   
;       Function:    void cx_w (char index, char val)
;
;       Purpose:        Write Cyrix Configuration Register at index with val
;       Inputs:         byte index, Cyrix Configuration Register
;                       byte val, value to be written to index
;       Output:         nothing
;**************************************************************************
_cx_w    proc    near
    push    bp
    mov    bp,sp
        pushf                           ; save flags
        cli                             ; clear interrupt in flags
    mov    al, byte ptr [bp+4]     ; get index
        out    22h, al                 ; tell CPU which config. register
    mov    al, byte ptr [bp+6]     ; get val
    out    23h, al                 ; write to CPU config. register
        popf                            ; restore flags
    mov    sp,bp
    pop    bp
    ret   
_cx_w    endp

.386p
;***********************************************************************
; Function:     void read_time_stamp( long*, long* );
; Purpose:      read Time Stamp Counter
;
; Inputs:       pointers to two longs
;               Param1 = Upper DWord
;               Param2 = Lower DWord
; Returns:      values of Time Stamp Counter
;
; NOTE:         You must check for TSC before using this function!!!
;***********************************************************************

_read_time_stamp proc near
    push    bp
    mov    bp, sp

        push    eax                       ; save off values
        push    edx
        push    si
       
        rdtsc                             ; db 0fh, 031h

        mov     si,word ptr [bp+4]
        mov     dword ptr [si],edx        ; param 1 = edx (Upper DWord)

        mov     si,word ptr [bp+6]
        mov     dword ptr [si],eax        ; param 2 = eax (Lower DWord)

        pop     si                        ; restore old values
        pop     edx
        pop     eax

        mov     sp,bp
        pop     bp
    ret
_read_time_stamp endp

;***********************************************************************
; Function:     unsigned long _cpu_speed( unsigned int )
;               "C" style caller
; Purpose:      calculate the elapsed time req'd to complete a loop of IDIVs
;
; Technique:    Use the PC's high resolution timer/counter chip (the 8254)
;               to measure elapsed time of a software loop consisting
;               of the IDIV and LOOP instruction.
; Definitions:  The 8254 recieves a 1.19318MHz clock (0.8380966 usec).
;               One "tick" is equal to one rising clock edge applied
;               to the 8254 clock input.
;
; Inputs:       ax = no. of loops for cpu_speed_loop
; Returns:      ax = no. of 1.19318MHz clk ticks req'd to complete the loop
;               dx = state of 8254 out pin
;***********************************************************************

PortB           EQU     061h
Timer_Ctrl_Reg  EQU     043h
Timer_2_Data    EQU     042h
stk$dx          EQU     10              ;dx register offset
stk$ax          EQU     14              ;ax register offset
stack$ax        EQU     [bp]+stk$ax
stack$dx        EQU     [bp]+stk$dx
Loop_Count      EQU     [bp+16]+4

_cpu_speed      proc near
        pushf                          ;save interrupt flag
        pusha                          ;pushes 16 bytes on stack
        mov     bp,sp                  ;init base ptr

        cli                            ;disable interrupts

;-------disable clock to timer/counter 2
        in      al, PortB
        and     al, NOT (1 SHL 0)      ; clear bit 0
        out     PortB, al
        mov     di, ax

;-------initialize the 8254 counter to "0", known value
        mov     al,0b0h
        out     Timer_Ctrl_Reg, al     ;control word to set channel 2 count
        mov     al,0ffh
        out     Timer_2_Data, al       ;init count to 0, lsb
        out     Timer_2_Data, al       ;init count to 0, msb

;-------get the number of loops from the caller's stack
        mov     cx,Loop_Count          ;loop count

;-------load dividend and divisor, clk count for IDIV depend on operands!
        xor     edx,edx                 ;dividend EDX:EAX
        xor     eax,eax
        mov     ebx,1                   ;divisor

;-------enable the timer/counter's clock. Begin timed portion of test!
        xchg    ax, di                  ;save ax for moment
        or      al, 1
        out     PortB, al               ;enable timer/counter 2 clk
        xchg    ax, di                  ;restore ax

;-------skip loop if Loop_Count = 0
        cmp     cx, 0
        jz      after_loop

;-------this is the core loop.
;        ALIGN 2                         ; This should really be ALIGN 16
cpu_speed_loop:
        idiv    ebx
        idiv    ebx
        idiv    ebx
        idiv    ebx
        idiv    ebx
        loop    cpu_speed_loop

after_loop:
;-------disable the timer/counter's clk.  End timed portion of test!
        mov     ax, di
        and     al, NOT (1 SHL 0)      ; clear bit 0
        out     PortB, al

;-------send latch status command to the timer/counter
        mov     al, 0c8h                ;latch status and count
        out     Timer_Ctrl_Reg, al

;-------read status byte, and count value "ticks" from the timer/cntr
        in      al, Timer_2_Data        ;read status
        mov     dl, al
        and     dx, 080h
        shr     dx, 7                   ; bit 0 = state of 8254 output pin

        in      al, Timer_2_Data        ;read LSB
        mov     bl, al
        in      al, Timer_2_Data        ;read MSB
        mov     bh, al

        not     bx                      ;invert count

;-------send command to clear the timer/counter
        mov     al, 0b6h
        out     Timer_Ctrl_Reg, al      ;clear channel 2 count
        xor     al, al
        out     Timer_2_Data, al        ;set count to 0, lsb
        out     Timer_2_Data, al        ;set count to 0, msb

;-------put return values on the stack for the caller
        mov     [bp+stk$ax], bx
        mov     [bp+stk$dx], dx

        popa
        popf                            ;restores interrupt flag
        ret
_cpu_speed      endp

_TEXT    ends

end

+ -

관련 글 리스트
6179 [급질문]CYRIX CPU 정보 알아내는 소스인데 ASM으로 된 함수를 참조 하는 방법 좀 가르쳐주세여. 허접푸케케 2257 2001/03/19
6200     Re:[급질문]CYRIX CPU 정보 알아내는 소스인데 ASM으로 된 함수를 참조 하는 방법 좀 가르쳐주세여. 박세용 2339 2001/03/19
6184     Re:[급질문]CYRIX CPU 정보 알아내는 소스인데 ASM으로 된 함수를 참조 하는 방법 좀 가르쳐주세여. 최혜원.시리 2540 2001/03/19
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.