|
asm으로 된 함수의 앞에 asm 으로 붙이고 사용하세요..
그리고 콜하는 부분은 함수로 처리하시고요..
한가지 예를 드리면 다음과 같습니다.
unsigned char inportb(unsigned short int port)
{
unsigned char value;
asm mov dx, port; // asm 을 붙인 것을 알 수 있지요??
asm in al, dx;
asm mov value, al;
return value;
}
즐거운 하루 되세요..
-----------------------------------------------------------------------------------------
허접푸케케 님이 쓰신 글 :
: 데브피아에서.. 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 R_eax,
: ; long R_ebx,
: ; long R_ecx,
: ; long R_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
:
|