home *** CD-ROM | disk | FTP | other *** search
- ; miscellaneous asm subroutines for the byte benchmarks
- ;
- ; BYTE Magazine, Spring 1990
- ;
- ; Modified 8/9/90 -- put in extra check for overflow in Getmhz - 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:
-
- 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
-