home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Zodiac Super OZ
/
MEDIADEPOT.ISO
/
FILES
/
13
/
4P_V331.ZIP
/
STAT.API
< prev
next >
Wrap
Text File
|
1996-06-01
|
12KB
|
210 lines
Description of the STAT.386 API v3.3.1 from 01.06.1996
=============================== STAT.386 driver v01.03
The file contains a description of the STAT.386 API (Application Program[ming]
Interface) and some programming examples for it.
1. Introduction
================
The STAT.386 driver was written by Ton Plooy (tonp@xs4all.nl) in December 1995
to make STAT.EXE runs under MS-Windows 3.1 or MS-Windows 95 too. To be able to
execute some iPentium-specific instructions, like RDTSC, RDMSR and WRMSR, your
code needs to run at CPL=0 (Code Privilege Level #0), to avoid exceptioms from
these instructions, listed above.
Because the DOS box under MS-Windows 3.1 or MS-Windows 95 runs at CPL=3 (which
is the lowest privilege level), you can't execute a RDMSR or WRMSR instruction
in the DOS box. This causes an exception and MS-Windows will close the DOS box
then. So you need -- somehow -- access to CPL=0.
Outside the MS-Windows DOS box STAT.EXE will use the VCPI API (Virtual Control
Program[ming] Interface), to enter CPL=0, execute the iPentium-specific RDTSC,
RDMSR or WRMSR instructions, and to return to CPL=3. (The VCPI API is provided
by most EMM386 drivers, as EMM386.EXE, QEMM386.SYS etc. If you load one of the
EMM386 drivers, then the driver kernel runs at CPL=0, to have the full control
over your machine, and your 'DOS command line' runs at CPL=3. So the processor
runs in virtual 8086 mode then.)
The STAT.386 driver is a MS-Windows VxD. On start up MS-Windows loads all VxDs
which are listed in the SYSTEM.INI file, section [386Enh]. There you will find
entries like 'DEVICE=x:\path\STAT.386'. Most VxDs contain an API, which can be
used by applications. And VxDs may contain code, which runs at CPL=0. So a VxD
is the key to CPL=0 under MS-Windows 3.1 or MS-Windows 95. (Another way is the
modification of the GDT (Global Descriptor Table). This table is not protected
by MS-Windows 3.1 or MS-Windows 95. So you could include a Call Gate into this
GDT and use it to enter CPL=0.)
So the STAT.386 driver provides an API for STAT.EXE and all other programs, to
execute the RDTSC, RDMSR and WRMSR instruction under MS-Windows 3.1 or MS-Win-
dows 95. The driver is only neccessary, when MS-Windows runs in enhanced mode,
because (a) VxDs are not used in standard mode and (b) MS-Windows will not use
its own virtual mode kernel in standard mode. (So if you run standard mode and
an EMM386 driver, then the VCPI API can be used from inside a DOS box too. But
if you run enhanced mode and an EMM386 driver, then the MS-Windows kernel will
replace the EMM386 driver's virtual mode kernel, and so the VCPI is disabled.)
2. The API
===========
First you must check, whether the INT 2Fh is handled by someone, or not. After
this check you can try to get the VxD entry point:
------------------------------------------------------------------------------
in: AX=1684h function 'Get VxD Entry Point'
BX=37DEh final unique VxD ID (assigned by Microsoft)
ES:DI=0000:0000h clear pointer for VxD entry point
use: INT 2Fh call multiplex interrupt
out: ES:DI=xxxx:xxxxh VxD entry point
------------------------------------------------------------------------------
If ES:DI returns not 0000:0000h, then the VxD is active (and so MS-Windows 3.1
or MS-Windows 95 runs in enhanced mode). So you can call this entry point then
for the following functions:
------------------------------------------------------------------------------
in: AX=0000h function 'Get STAT.386 Version'
use: call entry point call STAT.386 entry point
out: AX=xxyyh STAT.386 version xx.yy
rem: This function returns the internal STAT.386 driver version. The future
versions may have a different API. So do check for the correct version
before you call any function above 0000h!
------------------------------------------------------------------------------
in: AX=0001h function 'Execute RDTSC, RDMSR or WRMSR'
BX=00xxh 2nd opcode byte (30h, 31h or 32h)
EDX:EDI=64 bit input value for WRMSR
ECX=32 bit MSR number for RDMSR or WRMSR
use: call entry point call STAT.386 entry point
out: EDX:EAX=64 bit output value from RDTSC or RDMSR
rem: This function executes the RDTSC, RDMSR or WRMSR instruction. Load the
2nd opcode byte to BL (30h=WRMSR, 31h=RDTSC, 32h=RDMSR), the MSR # for
RDMSR or WRMSR to ECX and the MSR value for WRMSR to EDX:EDI.
The TSC or MSR value is returned in EDX:EAX. All unused register parts
should contain zero.
------------------------------------------------------------------------------
in: AX=0002h..FFFFh reserved for future use
use: call entry point call STAT.386 entry point
out: nothing reserved for future use
rem: All functions above 0001h are reserved for future use. Do not use them
at the moment, because this may cause trouble.
------------------------------------------------------------------------------
Attention! This API layout may be changed with future versions of the STAT.386
driver. Only function 0000h is guaranteed to stay stable.
3. Programming Example
=======================
The following Turbo/Borland Pascal unit is used by STAT.EXE to handle the VxD.
------------------------------------------------------------------------------
Unit CL_VxD; {uses the STAT.386 VxD}
INTERFACE {exported stuff}
Const VxD_ID : Word = $37DE; {final VxD ID value}
VxD_Ver_W : Word = $0103; {actual VxD version}
VxD_Ver_S : String[4] = '1.03'; {actual VxD version}
Function Check_VxD : Pointer; {the install check}
Function Get_VxD_Version : Word; {the installed version}
Procedure CPL0_VxD(B1:Byte; B2:Word; {the procedure itself}
Var W4,W3,W2,W1:Word);
IMPLEMENTATION {internal stuff}
Uses DOS; {for some INT stuff}
Var CPU : Registers; {for some INT stuff}
Entry_VxD : Pointer; {for VxD entry point}
a_Procedure : Procedure; {a dummy procedure}
{ The following function checks, whether the INT 2Fh is handled or not. Then }
{ it checks, whether the STAT.386 is loaded or not, and if it's loaded, then }
{ returns the VxD entry point. }
Function Check_VxD:Pointer; {the install check}
Var Int2F : Pointer; {for INT 2Fh handler}
Begin
GetIntVec($2F,Int2F); {get INT 2Fh handler}
Check_VxD:=NIL; {assume no VxD}
If Int2F<>NIL Then Begin {if INT 2Fh is handled}
CPU.AX:=$1684; {function 'Get API'}
CPU.BX:=VxD_ID; {signature "STAT.386"}
CPU.DI:=$0000; {prepare VxD entry}
CPU.ES:=$0000; {ES:DI->0000:0000}
INTR($2F,CPU); {call multiplex INT}
Check_VxD:=Ptr(CPU.ES,CPU.DI); {return VxD entry}
End;
End;
{ The following function returns an internal STAT.386 VxD version. If no VxD }
{ is installed, then it returns 0000h for the version. The value 0100h would }
{ indicate a version 01.00 for STAT.386. }
Function Get_VxD_Version:Word; {the installed version}
Var Version:Word; {for a dummy value}
Begin
Version:=$0000; {assume version 00.00}
If Entry_VxD<>NIL Then Begin {only if installed}
CPU.AX:=$0000; {function 0000h}
a_Procedure; {do the CPL0 access}
Asm MOV [Version],AX End; {return version}
End;
Get_VxD_Version:=Version; {return version value}
End;
{ The following procedure executes the RDTSC, RDMSR or WRMSR instruction. It }
{ needs the 2nd opcode byte stored in B1, the MSR number in B2 (so here only }
{ MSR numbers from 0..FFh are supported, because B2 is a byte value) and the }
{ 64 bit wide MSR value in W4:W3:W2:W1 (W4=highest part..W1=lowest part). On }
{ RDTSC or RDMSR it returns the TSC or MSR value in W4:W3:W2:W1. }
{ Attention! Because the Turbo/Borland Pascal's integrated assembler doesn't }
{ support 32 bit code, some DB 66h statements must be used. Because there is }
{ no variable type for the 64 bit unsigned integer value available, 4x16 bit }
{ wide word variables must be used. :-( }
Procedure CPL0_VxD(B1:Byte; B2:Word; {the procedure itself}
Var W4,W3,W2,W1:Word);
Var WW4,WW3,WW2,WW1 : Word; {for some dummy values}
Begin
WW4:=W4; WW3:=W3; WW2:=W2; WW1:=W1; {get input values}
If Entry_VxD<>NIL Then Begin {only if installed}
Asm
DB 66h; XOR BX,BX; MOV BL,[B1] {MOV EBX,[B1]} {store 2nd opcode byte}
DB 66h; XOR CX,CX; MOV CX,[B2] {MOV ECX,[B2]} {store MSR number}
MOV AX,[WW4]; PUSH AX; MOV AX,[WW3]; PUSH AX {store EDX}
DB 66h; POP DX {MOV EDX,[W4:W3]}
MOV AX,[WW2]; PUSH AX; MOV AX,[WW1]; PUSH AX {store EDI}
DB 66h; POP DI {MOV EDI,[W2:W1]}
MOV AX,1 {function 0001h}
End;
a_Procedure; {do the CPL0 access}
Asm
DB 66h; PUSH AX; {MOV [W2:W1],EAX}
POP AX; MOV [WW1],AX; POP AX; MOV [WW2],AX; {return EAX}
DB 66h; PUSH DX; {MOV [W4:W3],EDX}
POP AX; MOV [WW3],AX; POP AX; MOV [WW4],AX; {return EDX}
End;
End;
W4:=WW4; W3:=WW3; W2:=WW2; W1:=WW1; {return values}
End;
{ The following part of this unit will be executed on start up of a program, }
{ which includes this unit. It checks for the installed and active STAT.386, }
{ and it modifies the variable a_Procedure, so that this procedure points to }
{ the VxD entry point. }
{ Attention! Do include this check for the installed STAT.386 into your code }
{ again, before you call one of the VxD functions. }
Begin {init}
Entry_VxD:=Check_VxD; {get VxD entry}
If Entry_VxD<>NIL Then Begin {if VxD is installed}
Seg(a_Procedure):=MemW[Seg(Entry_VxD):Ofs(Entry_VxD)+2]; {point to entry}
Ofs(a_Procedure):=MemW[Seg(Entry_VxD):Ofs(Entry_VxD)+0]; {point to entry}
End;
End.
------------------------------------------------------------------------------
*** END OF FILE ***