home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR2
/
BYTE24.ZIP
/
MISCSUBS.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-05-22
|
16KB
|
997 lines
; miscellaneous asm subroutines for the byte benchmarks
;
; BYTE Magazine, Spring 1990
;
; Modified 8/9/90 -- put in extra check for overflow in Getmhz - Steve.
; 5/15/91 -- patch - stubbed out getmhz due to incompatibility - Steve.
;
_data segment word public 'DATA'
control dw ? ;For floating-point control word
cap_reqd dw ? ; disk capacity required
dw ?
extrn video_seg: WORD
_data ends
dgroup group _data
assume cs:_text, ds:dgroup
public _strip0s, _machine_detect, _disk_check, _set_default, _get_default
public _getpath, _cdir, _click
_text segment byte public 'CODE'
_strip0s proc near
; void strip0s(char *buffer, unsigned int buflen);
; strips (turns into spaces) zeros from a char buffer.
;
strip0sframe struc
s0bptr dw ?
s0raddr dw ?
s0bufptr dw ?
s0buflen dw ?
strip0sframe ends
s0sframe equ [bp-s0bptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,s0bptr
push di
push es
mov cx, s0sframe.s0buflen
jcxz S0EXIT
push ds
pop es
mov ax, s0sframe.s0bufptr
mov di, ax
xor al, al
S0S0:
repne scasb
jne S0EXIT
dec di
inc cx
mov byte ptr [di], ' '
jmp short S0S0
S0EXIT:
pop es
pop di
pop bp
ret
_strip0s ENDP
;-----------------------------------------------------------
getproc proc near
; detects processor type
; returns value in ax
; This routine is adapted from Michael Young's _MS-DOS_Advanced_
; Programming_
push di
push es
pushf
; 808x test
; Attempt to zero flag register. If four high-order bits still
; set, its an 808x.
;
xor ax, ax
push ax
popf
pushf
pop ax
and ax, 0f000h
cmp ax, 0f000h
jne GP186TEST
mov ax, 86
jmp short GPEXIT
GP186TEST:
; 186 test
; Push SP. 80186 decrements SP before pushing, so popped SP will
; not be equal. 286 and 386 decrement after push.
push sp
pop ax
cmp ax, sp
je GP286TEST
mov ax, 186
jmp short GPEXIT
GP286TEST:
; 286 test
; Attempt to set bits 15-12 of the flags register. If they don't set,
; it's a 286.
mov ax, 0f000h
push ax
popf
pushf
pop ax
and ax, 0f000h
jnz GP386
mov ax, 286
jmp short GPEXIT
GP386:
; all that's left. 486s and sxes are not considered.
mov ax, 386
GPEXIT:
popf
pop es
pop di
ret
getproc ENDP
;-----------------------------------------------------------
getfpu proc near
; detects fpu type
; returns value in ax
push di
push es
mov bx, ax
int 11h
and ax, 02h
jz FPUEXIT ; no fpu installed
cmp bx, 286
jle FNOT386
; Test for 287 or 387. This code adapted from the defunct but
; fondly remembered PC Tech Journal.
finit
fld1
fldz
fdiv ;Create infinity
fld st
fchs ;Create negative infinity
fcompp ;Compare
fstsw control ;Save control word
fwait ;Just in case...
mov ax,control
sahf ;Control word in flags
mov ax,287 ;Assume 80287
jz FIS287
mov ax,387 ;Nope, 80387
FIS287:
jmp short FPUEXIT
FNOT386:
mov ax, bx
inc ax
FPUEXIT:
pop es
pop di
ret
getfpu ENDP
;-----------------------------------------------------------
getmhz proc near
; this routine determines machine approximate speed for use in later
; estimates. while it uses as few memory accesses as possible, it will
; be affected by memory speed.
; On entry -- ax= proc type, 88=8088, etc.
; On exit -- ax = approx megahertz.
jmp short GMHREALSTART
checkval db 0
convfact dw 0
; checkval == 1 if main routine has initialized and counter is
; ready to run, 0 otherwise
; bl is the pass counter
FACT88 equ 7002
FACT286 equ 4091
FACT386 equ 3210
GMH1CHANDLER:
push ax
push cs
pop ds
mov al, 1
cmp al, checkval
jne GMHCHAIN
; now initialize routine has zeroed bx if this is the first pass
inc bl
cmp al, bl
je ONETWOEXIT ; its the first pass
mov checkval, 0 ; clear checkval so we're done
ONETWOEXIT:
pop ax
iret
GMHCHAIN:
pop ax
db 0eah ; sleazy far jump trick
gmhovo dw 0
gmhovs dw 0
GMHREALSTART:
;************* this routine has been stubbed out because of interrupt
;************* incompatibility in some systems - 5/91
mov ax, 20 ; patched for unclean interrupts
ret
push di
push es
push ds
push cs
pop ds
; store conversion factor
cmp ax, 386
jl GMH28
mov convfact, FACT386
jmp short GMFACTDONE
GMH28:
cmp ax, 286
jl GMH88
mov convfact, FACT286
jmp short GMFACTDONE
GMH88:
mov convfact, FACT88
GMFACTDONE:
; install new int 1c handler
; get old owner's address and install
mov ax,351ch ; prepare for function call
int 21h ; get address of int 1c handler in es:bx
mov gmhovo, bx
mov gmhovs, es
mov dx, offset GMH1CHANDLER
mov ax, 251ch
int 21h
mov al, 1
xor cx, cx
xor dx, dx
xor bx, bx
; turn on interrupt
cli
mov checkval, al
sti
GML0:
cmp al, bl
jg GML0
GML1:
cmp al, bl
jl DONE
loop GML1
dec dx
jmp short GML1
DONE:
; now hibits are in dx, lobits are in cx
push dx
push cx
; uninstall the nasty handler
mov dx, gmhovo
mov ax, gmhovs
mov ds, ax
mov ax, 251ch
int 21h
; mov numbers to dx:ax
pop ax
pop dx
neg dx
neg ax
; compensate for time spent in interrupts
add ax, 15
adc dx, 0
; multiply by conversion factor to get thousands of cycles per second --
push dx ; save high order
mov bx, convfact
mul bx
pop cx ; old high order
push ax ; new low order
push dx ; new high order
mov ax, cx
mul bx
; if dx is not clear we're going to overflow
cmp dx, 0
je GMNOOFLOW
pop ax
pop ax
pop ds
mov ax, 0ffffh
ret
GMNOOFLOW:
pop dx
add dx, ax ; multiplied result
pop ax
; divide by 10000
mov bx, 10000
cmp bx, dx
jle GMOFLOW2
div bx
jmp short GMNOOFLOW2
GMOFLOW2:
mov ax, 0ffffh ; fastest machine there is
GMNOOFLOW2:
; further divide by 1000 to convert to MHz
xor dx, dx
mov bx, 1000
div bx
sar bx,1
cmp dx, bx
jl GMNOROUNDUP
inc ax
GMNOROUNDUP:
pop ds
pop es
pop di
ret
getmhz ENDP
;-----------------------------------------------------------
getga proc near
; detects graphics adapter
; returns value in ax
; sets up the proper video segment for windowing routines.
; Adapted from routines in _Programmer's_Guide_to_PC_and_PS/2_
; _Video_Systems_, by Richard Wilton
;
; Function returns the following values:
; MDA - 6 CGA, - 3 None - 0
; HERC - 5 EGA, Enhanced color - 2
; EGA, Mono - 4 VGA - 1
;
push di
push es
xor ax,ax ;PS/2
mov ax,1A00h
int 10h
xor bh,bh ;Discard inactive
mov cl,bl
xor bl,bl
cmp cl,7 ;7 and 8 are VGA
jne DUMMY
jmp VGAFND
DUMMY: cmp cl,8
jne DUM1
jmp VGAFND
DUM1: mov bl,10h
mov ah,12h
int 10h
cmp bl,10h
je CGATST
xor bx,bx
mov ax,40h ;EGA maybe
mov es,ax
mov al,es:[87h]
test al,08h ;Test if EGA present but inactive
jnz CGATST
test al,02h ;Test if EGA has mono display
jnz EGMFND
jmp EGAFND
CGATST: mov ah,0Fh ;Determine if any monochrome displays active
int 10h ; before continuing
cmp al,7
je MDATST
xor bx,bx
mov dx,3D4h
mov al,0Fh
out dx,al
inc dx
in al,dx
mov ah,al
mov al,77h ;Arbitrary write value to test for 6845
out dx,al
mov cx,100h
STALL1: loop STALL1
in al,dx
xchg ah,al
out dx,al ;Put it back
cmp ah,77h
je CGAFND
MDATST: xor bx,bx
mov dx,3b4h ;Same test, new address, for MDA, Herc
mov al,0Fh
out dx,al
inc dx
in al,dx
mov ah,al
mov al,77h ;Arbitrary write value to test for 6845
out dx,al
mov cx,100h
STALL2: loop STALL2
in al,dx
xchg ah,al
out dx,al ;Put it back
cmp ah,77h
jne LOST ;Out of possibilities
mov dx,3BAh ;Differentiate between MDA, Herc
in al,dx
and al,80h
mov ah,al
mov cx,8000h ;Wait 32 768 tries
STALL3: in al,dx ;Keep checking if bit changes
and al,80h
cmp ah,al
loope STALL3
je MDAFND
inc bx
cmp bx, 50 ; make it change over and over
jb STALL3
xor bx, bx
jmp HRCFND
MDAFND: mov bx,1 ;MDA start incrementing
HRCFND: inc bx ;Different increments for different cards
EGMFND: inc bx
CGAFND: inc bx
EGAFND: inc bx
VGAFND: inc bx
LOST: mov ax,bx
cmp ax, 3
jg VIDEOFOUND
push ax
mov ah, 0fh
int 10h
cmp al, 07h
pop ax
je VIDEOFOUND
; vga, ega, or cga display found
push ax
mov ah, 0fh
int 10h
; now current page is in bh
mov ax, 100h
mul bh
add ax, 0b800h
mov video_seg, ax
pop ax
VIDEOFOUND:
pop es
pop di
ret
getga ENDP
;-----------------------------------------------------------
getnumh proc near
; detects number of hard disks
; returns value in ax
push di
push es
mov ah, 8
mov dl, 80h
int 13h
jnc NHOKAY
xor ax, ax
jmp short NHEXIT
NHOKAY:
mov al, dl
xor ah, ah
NHEXIT:
pop es
pop di
ret
getnumh ENDP
;-----------------------------------------------------------
_machine_detect proc near
; void machine_detect (struct mcfig*);
; Detects processor speed and type, fpu, and graphics type, number
; of hard disks.
mac_d struc
mdbptr dw ?
mdraddr dw ?
mdhandle dw ?
mac_d ends
; structure equates
graphics_type equ word ptr [di+15]
proc_type equ word ptr [di+17]
fpu_type equ word ptr [di+19]
MHz equ word ptr [di+21]
num_hard equ word ptr [di+23]
mdframe equ [bp-mdbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,mdbptr
push di
push es
push ds
pop es
mov ax, mdframe.mdhandle
mov di, ax
; call detector routines
; all routines but getmhz and getfpu take no arguments and return value in ax
call getga
mov graphics_type, ax
call getproc
mov proc_type, ax
push ax
; getfpu and getmhz take proc_type in ax, so must follow getproc
call getfpu
mov fpu_type, ax
pop ax
call getmhz
mov MHz, ax
call getnumh
mov num_hard, ax
pop es
pop di
pop bp
ret
_machine_detect ENDP
;-----------------------------------------------------------
_disk_check proc near
; int disk_check (int drive number, int capcheckflag);
;
; given 1-based drive number returns 1 or zero based on the following:
; If the drive is not ready or invalid, return -1.
; If the drive is a floppy, return FLOPPY_KBYTES_REQD if
; space is available; 0 if not.
; If the drive is a hard drive, return HD_KBYTES_REQD if space is
; available; 0 if not.
;
; if capcheckflag == 0, do not ready or invalid check only.
;
;
FLOPPY_BYTES_REQD equ 500
HD_BYTES_REQD equ 2000
driv_ck struc
dcbptr dw ?
dcraddr dw ?
drivnum dw ?
dcapflag dw ?
driv_ck ends
; structure equates
dcframe equ [bp-dcbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,dcbptr
push ds
push es
push di
; determine if fixed or floppy using dos-free ioctl
mov ax, 4408h
mov bx, dcframe.drivnum
int 21h
jc DCNOTRMV
cmp al, 1
je DCNOTRMV
; check for drive not ready errors using bios, so no Abort,... message
; first get a buffer
mov bx, 33 ; paranoia
mov ah, 48h
int 21h
jnc DC_GOT_MEMORY
mov ax, -1
jmp DCEXIT
DC_GOT_MEMORY:
mov es, ax
mov cx, 3
DC_TRYAGAIN:
xor bx, bx
mov dx, dcframe.drivnum
xor dh, dh
dec dl
push cx
mov cx, 1
mov ax, 0401h ; verify sector 0, cyl 0, head 0
int 13h
pop cx
jnc DCDRIVEREADY
xor ah, ah
int 13h ; reset before trying again
loop DC_TRYAGAIN
; lose
mov ah, 49h
int 21h
mov ax, -1
jmp short DCEXIT
DCDRIVEREADY:
mov ah, 49h ; deallocate memory
int 21h
DCNOTRMV:
; stop here if you don't care about capacity
mov ax, dcframe.dcapflag
cmp ax, 0
jne DCCONTINUE
mov ax, 1
jmp short DCEXIT
DCCONTINUE:
; dos check
push ds
mov ah, 1ch
mov dx, dcframe.drivnum
int 21h
; return -1 on error
cmp al, 0ffh
jne DCNOERR
cbw
pop ds
jmp short DCEXIT
DCNOERR:
; is this is a floppy?
mov bl, [ds:bx]
pop ds
cmp bl, 0f8h
je DCHARD
; is it a 360k or non-standard (720k 5.25) drive?
cmp bl, 0fch
jl DCFLOPOK
xor ax, ax
jmp short DCEXIT
DCFLOPOK:
mov bx, FLOPPY_BYTES_REQD
jmp short CAPCHECK
DCHARD:
mov bx, HD_BYTES_REQD
CAPCHECK:
push bx ; return value, eventually
mov ax, 1024
mul bx
mov cap_reqd, ax
mov cap_reqd+2, dx ; save required bytes
mov ah, 36h
mov dx, dcframe.drivnum
int 21h
; determine if space is available
push bx ; clusters available
push ax ; sectors per cluster
push cx ; bytes per sector
mov dx, cap_reqd+2
mov ax, cap_reqd
pop bx ; bytes per sector
div bx ; should leave the result a word for all reasonable
; space required (up to 32 megs at 512 bytes/sec)
xor dx,dx
pop bx ; sectors per cluster
div bx
xor dx, dx
pop bx ; clusters available
cmp bx, 0
je DCLOSER
div bx
; as long as ax is zero, we're fine
cmp ax, 0
jne DCLOSER
pop ax
jmp short DCEXIT
DCLOSER:
pop ax ; bytes reqd - don't need now
xor ax, ax
DCEXIT:
pop di
pop es
pop ds
pop bp
ret
_disk_check ENDP
;___________________________________________________________________
_get_default proc near
; int get_default (void);
;
; Get default drive
def_drive struc
ddbptr dw ?
ddraddr dw ?
def_drive ends
; structure equates
ddframe equ [bp-ddbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,ddbptr
mov ah, 19h
int 21h
xor ah, ah
pop bp
ret
_get_default ENDP
;___________________________________________________________________
_set_default proc near
; void set_default (int);
;
; Get default drive
sdef_drive struc
sdbptr dw ?
sdraddr dw ?
sddrive dw ?
sdef_drive ends
; structure equates
sdframe equ [bp-sdbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,sdbptr
mov ah, 0eh
mov dx, sdframe.sddrive
int 21h
pop bp
ret
_set_default ENDP
;-----------------------------------------------------------
_getpath proc near
; void getpath (int drive, char * bufptr);
;
; Get current path
g_path struc
gpbptr dw ?
gpraddr dw ?
gpdrive dw ?
gp_pptr dw ?
g_path ends
; structure equates
gpframe equ [bp-gpbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,gpbptr
push si
mov dx, gpframe.gpdrive
inc dl ; make it 1-based
mov ax, gpframe.gp_pptr
mov si, ax
mov ah, 47h
int 21h
pop si
pop bp
ret
_getpath ENDP
;-----------------------------------------------------------
_cdir proc near
; int cdir (char * path);
;
; Change directories
c_dir struc
chdbptr dw ?
chdraddr dw ?
chd_pptr dw ?
c_dir ends
; structure equates
chdframe equ [bp-chdbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,chdbptr
mov dx, chdframe.chd_pptr
xor bx, bx
mov ah, 3bh
int 21h
adc bx, 0
not bl
and bl, 1
mov ax, bx
pop bp
ret
_cdir ENDP
;-----------------------------------------------------------------
_click proc near
PPI_61 equ 61h ; -enable keyboard or
; +clear keyboard (bit 7)
;
; void click( void);
;
clik struc
clkbptr dw ?
clkraddr dw ?
clik ends
; structure equates
clkframe equ [bp-clkbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,clkbptr
; Make a keyclick
mov bx,08
click_loop:
in al,PPI_61
or al,2 ; Speaker on
out PPI_61,al
mov cx,0060
click1:
loop click1
and al,0fdh ; Speaker off
out PPI_61,al
mov cx,0060
click2:
loop click2
dec bx
jnz click_loop
click_out:
pop bp
ret
_click endp
;-----------------------------------------------------------
_text ends
END