home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
pcmag
/
vol6n03.arc
/
CHECK.ASM
next >
Wrap
Assembly Source File
|
1987-12-13
|
26KB
|
481 lines
;CHECK.COM for the IBM Personal Computer - 1986 by Jeff Prosise
.8087 ;recognize 8087/80287 instructions
code segment para public 'code'
assume cs:code,ds:code
org 100h
begin: jmp check ;skip data area
;
notice db ' Copyright 1986 Ziff-Davis Publishing Co.'
notice_2 db ' Programmed by Jeff Prosise'
keywords db 'MEMORY',0,'FILESIZE',0,'VIDEOCARD',0
db 'MODEL',0,'8087',0,'80287',0
db 'FILEFOUND',0,'FILETEXT',0,'DISKSPACE',0
db 'VIDEOMODE',0,'TIME',0,'DAY',0,'MONTH',0
db 'VERSION',0,'KEYBOARD',0,'KEYPRESS',0
;
jump_table dw offset keypress ;vector dispatch table
dw offset keyboard
dw offset version
dw offset month
dw offset day
dw offset time
dw offset videomode
dw offset diskspace
dw offset filetext
dw offset filefound
dw offset mathproc
dw offset mathproc
dw offset model
dw offset videocard
dw offset filesize
dw offset memory
;
ibm db 'IBM' ;EGA signature
parameter_count db ? ;number of command line parameters
string_length dw 0 ;length of text string in bytes
file_handle dw ? ;storage area for DOS file handle
command_index dw ? ;storage for parsing index
keyword_buffer dw offset endprog ;pointer to keyword buffer
param1_buffer dw offset endprog+16 ;pointer to parameter buffer
text_string dw offset endprog+144 ;pointer to text string buffer
dta dw offset endprog+272 ;pointer to Disk Transfer Area
control_bytes label byte ;byte accessor to control word
control_8087 dw 0 ;8087/80287 control word
;
errmsg1 db 13,10,'Invalid Keyword',13,10,'$'
errmsg2 db 13,10,'Missing Parameter',13,10,'$'
errmsg3 db 13,10,'Invalid Drive Specifier',13,10,'$'
errmsg4 db 13,10,'Invalid String Specifier',13,10,'$'
errmsg5 db 13,10,'File Not Found',13,10,'$'
;
check proc near
cld ;clear DF for string instructions
call parse_line ;parse command line for entries
cmp parameter_count,0 ;any parameters entered?
jne check1 ;yes, then continue
lea dx,errmsg2 ;no - load error msg address
jmp error1 ;abort on error
check1: lea si,keywords ;point SI to keyword list
mov cx,16 ;number of reserved keywords
check2: mov di,keyword_buffer ;point DI to keyword just entered
check3: lodsb ;get character
or al,al ;is it a zero byte?
je match_found ;yes, then keywords match
scasb ;compare it to byte in buffer
je check3 ;loop back on match
dec cx ;no match - decrement counter
jcxz error_exit ;list scanned unsuccessfully
check4: lodsb ;index SI to next word in list
or al,al ;is this byte a zero?
jne check4 ;no, try again
jmp check2 ;SI set - try another keyword
;
;Execution comes here when the keyword entered on the command line matches one
;of the recognized keywords. The count in CX is translated into a pointer to
;the address of the routine to be vectored to.
;
match_found: mov bx,cx ;get keyword number in BX
dec bx ;decrement it by 1
shl bx,1 ;multiply by two to form index
jmp word ptr cs:[offset jump_table+bx] ;goto handler
;
;Execution comes here when an error is encountered.
;
error_exit: lea dx,errmsg1 ;load address of error message
error1: push ax ;save error return code in AL
mov ah,9 ;DOS function - Print String
int 21h ;print error message
pop ax ;retrieve return code
;
;EXIT is the common point of exit for all routines in the program. A return
;code is set that can be read as the ERRORLEVEL parameter by batch processes.
;
exit: mov ah,4Ch ;DOS function - Exit Program
int 21h ;exit with return code
check endp
;
;Model routine returns the machine ID byte of the computer being used.
;
model proc near
mov ax,0F000h ;set ES to ROM segment
mov es,ax
mov di,0FFFEh ;load DI with offset of ID byte
mov al,es:[di] ;get machine ID byte into AL
jmp exit ;exit
model endp
;
;VideoMode routine returns the current video mode (0-16).
;
videomode proc near
mov ah,15 ;INT 10h function - Get Video Data
int 10h ;get video mode in AL
jmp exit ;exit
videomode endp
;
;VideoCard routine returns a value indicating what kind of video adapter is
;being used in the system (0=MDA, 1=CGA, 2=EGA).
;
videocard proc near
mov dl,2 ;initialize DL
mov bx,0C000h ;set ES to EGA BIOS segment
mov es,bx
mov di,1Eh ;set DI to IBM signature address
lea si,ibm ;set SI to 'IBM' text
mov cx,3 ;three bytes to check
repe cmpsb ;compare the three bytes
je card1 ;this is an EGA - jump to exit
dec dl ;adjust DL for MDA or CGA
mov ah,15 ;get current video mode
int 10h
cmp al,7 ;is it mode 7?
jne card1 ;no, then this is a CGA
dec dl ;zero DL for MDA
card1: mov al,dl ;set AL for exit
jmp exit ;and exit
videocard endp
;
;Memory routine returns the number of 16K RAM modules present in the system.
;
memory proc near
int 12h ;get memory size from BIOS
mov cl,4 ;set CL to 4 for shift
shr ax,cl ;shift 4 times to divide by 16
jmp exit
memory endp
;
;FileFound returns 0 if the indicated file is found, 1 if it's not.
;
filefound proc near
cmp parameter_count,1 ;more than 1 parameter entered?
ja filefnd1 ;yes, then continue
lea dx,errmsg2 ;no, then get error msg address
mov al,1 ;set AL to 1 to indicate failure
jmp error1 ;and exit
filefnd1: mov dx,param1_buffer ;point DX to filename
mov ah,3Dh ;use DOS Open File function
xor al,al ;set AL to 0 for read-only access
int 21h ;attempt to open the file
jnc filefnd2 ;open process succeeded
mov al,1 ;open failed - set AL to 1
jmp exit
filefnd2: mov bx,ax ;get file handle in BX
mov ah,3Eh ;use DOS Close File function
int 21h ;close file just opened
xor al,al ;zero AL for exit
jmp exit
filefound endp
;
;KeyBoard returns 1 if a key has been pressed, 0 if one has not.
;
keyboard proc near
mov ah,1 ;use BIOS to check buffer
int 16h ;get status of keyboard buffer
je kb1 ;empty if ZF set
mov al,1 ;not empty - set AL to 1
jmp exit
kb1: xor al,al ;buffer empty - zero AL
jmp exit
keyboard endp
;
;KeyPress returns waits for a keypress (if one isn't already buffered) and
;returns its ASCII code.
;
keypress proc near
mov ah,0 ;use BIOS function to read keypress
int 16h ;get keypress - ASCII code in AL
jmp exit
keypress endp
;
;Version returns the major number of the version of DOS in use.
;
version proc near
mov ah,30h ;use DOS Get Version function
int 21h ;get version number
jmp exit
version endp
;
;DiskSpace returns the number of whole 16K blocks of free disk space from the
;indicated or default drive. AL is 0 on exit if an error is encountered. A
;return value of 255 means there are that many blocks or more free.
;
diskspace proc near
xor dl,dl ;set DL to 0 for default drive
cmp parameter_count,1 ;only one parameter entered?
je dspace1 ;yes, then use default drive
mov si,param1_buffer ;set SI to parameter text
lodsb ;get first character in parameter
sub al,64 ;convert to DOS drive designator
mov dl,al ;shift designator to DL
lodsb ;get following character
cmp al,':' ;is it a colon?
je dspace1 ;yes, then continue
lea dx,errmsg3 ;no, then load error msg address
xor al,al ;set AL for failure
jmp error1 ;exit on error
dspace1: mov ah,36h ;use DOS Get Free Space function
int 21h ;get disk information
cmp ax,0FFFFh ;drive designator error?
jne dspace2 ;no, then continue
lea dx,errmsg3 ;abort on drive error
xor al,al
jmp error1
dspace2: mul cx ;multiply to get bytes per cluster
mul bx ;multiply again to get free bytes
mov cx,14 ;set shift counter
dspace3: shr dx,1 ;shift AX:DX right 14 bits
rcr ax,1
loop dspace3 ;loop until done
or ah,ah ;is the MSB zero?
je dspace4 ;yes, then continue
mov al,255 ;no, then set AL to 255
dspace4: jmp exit
diskspace endp
;
;Time returns the current hour of the day (0-23).
;
time proc near
mov ah,44 ;get current time from DOS
int 21h
mov al,ch ;place hour in AL
jmp exit
time endp
;
;Day returns the current day of the month (1-31).
;
day proc near
mov ah,42 ;get current date from DOS
int 21h
mov al,dl ;put day in AL
jmp exit
day endp
;
;Month returns the current month number (1-12).
;
month proc near
mov ah,42 ;get date from DOS
int 21h
mov al,dh ;put month in AL
jmp exit
month endp
;
;FileText returns 0 if the specified string is found within the indicated
;file. A 1 is returned if the string is not contained within the file, if
;the file is not found, or if a syntax error is detected on the command line.
;
filetext proc near
cmp parameter_count,2 ;at least two parameters entered?
je text1 ;yes, then continue
lea dx,errmsg2 ;no, then abort
mov al,1
jmp error1
text1: mov si,command_index ;point SI to end of second param
mov di,text_string ;point DI to string buffer
text2: lodsb ;get next character
cmp al,32 ;is it a space character?
je text2 ;yes, then go back for another
cmp al,39 ;is it a quote mark?
je text4 ;yes, then branch and continue
cmp al,13 ;end-of-line marker?
jne text3 ;no, it's an invalid character
lea dx,errmsg2 ;abort - string missing
mov al,1
jmp error1
text3: lea dx,errmsg4 ;abort - syntax error in string
mov al,1
jmp error1
text4: lodsb ;get character in string
cmp al,13 ;end-of-line marker?
je text3 ;yes, then abort
cmp al,39 ;quote mark?
je text5 ;yes, then end of string reached
stosb ;copy character to string buffer
inc string_length ;increment length count
jmp text4 ;go back for another character
text5: cmp string_length,0 ;any characters in string?
jne text6 ;yes, then continue
lea dx,errmsg4 ;no, then abort
mov al,1
jmp error1
text6: mov dx,param1_buffer ;point DX to filename
mov ah,3Dh ;open the file
xor al,al
int 21h
jnc text7 ;continue if open succeeded
lea dx,errmsg5 ;abort if it failed
mov al,1
jmp error1
text7: mov file_handle,ax ;save file handle
text8: mov dx,dta ;point DX to Data Transfer Area
mov cx,0C000h ;specify C000h bytes to be read
mov bx,file_handle ;get DOS file handle
mov ah,3Fh ;DOS function - Read Block
int 21h ;read block from file on disk
cmp ax,string_length ;enough bytes read in to compare?
jb not_found ;no, then terminate
mov bx,ax ;save actual bytes read in BX
mov cx,ax ;prepare CX for comparison loop
sub cx,string_length
inc cx
mov di,dta ;point DI to block just read
text9: push cx ;save loop counter
push di ;save start index
mov cx,string_length ;prepare to compare string
mov si,text_string ;point SI to string text
repe cmpsb ;compare while equal
pop di ;restore saved registers
pop cx
je text_found ;match found if ZF set
inc di ;increment starting index
loop text9 ;loop until entire block examined
cmp bx,0C000h ;was end-of-file reached?
jne not_found ;yes, then exit - string not found
mov ah,42h ;DOS function - Move File Pointer
mov al,1 ;method code - current pos + offset
mov cx,0FFFFh ;form negative integer in DX:CX
mov dx,string_length ;get string length in low word
not dx ;form complement
add dx,1 ;form two's complement
adc cx,0 ;carry into high word (CX)
mov bx,file_handle ;get file handle
int 21h ;move file pointer back
jmp text8 ;read another block from disk
text_found: xor al,al ;text found - zero AL
jmp close_file
not_found: mov al,1 ;text not found - set AL to 1
close_file: push ax ;save return code in AL
mov ah,3Eh ;close file before exiting
mov bx,file_handle
int 21h
pop ax ;restore AL
jmp exit
filetext endp
;
;FileSize returns the length in kilobytes of the specified file. A value of
;255 means the file is 255K or greater in length. 0 is returned if the file
;cannot be found.
;
filesize proc near
cmp parameter_count,1 ;more than 1 parameter entered?
ja size1 ;yes, then continue
lea dx,errmsg2 ;no filename - abort
xor al,al
jmp error1
size1: mov dx,param1_buffer ;point DX to ASCIIZ filename
mov ah,3Dh ;use DOS Open File function
xor al,al ;open for reading only
int 21h ;open the file
jnc size2 ;continue if open succeeded
lea dx,errmsg5 ;abort if it did not
xor al,al
jmp error1
size2: push ax ;save file handle on stack
mov bx,ax ;get file handle in BX
mov ah,42h ;use DOS to move file pointer
mov al,2 ;method code - EOF + offset
xor cx,cx ;specify 0 offset in DX:CX
xor dx,dx
int 21h ;move file pointer to EOF
pop bx ;get file handle
push ax ;save EOF address
push dx
mov ah,3Eh ;close file
int 21h
pop dx ;retrieve address
pop ax
mov cl,10 ;prepare CL for shift
size3: shr dx,1 ;shift AX:DX right 10 bits
rcr ax,1
loop size3
or dx,dx ;DX = 0 ?
jne max_length ;no, filesize > 255K
or ah,ah ;AH = 0 ?
jne max_length ;no, filesize > 255K
jmp exit ;length in AL
max_length: mov al,255 ;set AL to 255 for exit
jmp exit
filesize endp
;
;Mathproc returns a 1 if neither an 8087 nor an 80287 math coprocessor is
;detected in the system or a 0 if one of them is.
;
mathproc proc near
fninit ;initialize (set control word)
fnstcw control_8087 ;write control word to memory
cmp control_bytes[1],3 ;control word correctly written?
je found_8087 ;yes, then 8087/80287 is there
mov al,1 ;no coprocessor - set AL to 1
jmp exit
found_8087: xor al,al ;zero AL
jmp exit
mathproc endp
;
;------------------------------------------------------------------------------
;PARSE_LINE parses the command line for the first two parameters entered and
;writes them into their respective storage buffers.
;------------------------------------------------------------------------------
parse_line proc near
mov parameter_count,0 ;zero count of entries
mov si,81h ;set SI to start of text
call next_parameter ;index to next parameter
jc parse_exit ;exit if there's not one
mov di,keyword_buffer ;set DI for output
call get_parameter ;parse parameter to buffer
inc parameter_count ;increment count
call next_parameter ;index to next parameter
jc parse_exit ;exit if there's not one
mov di,param1_buffer ;set DI for output
call get_parameter ;get next parameter
inc parameter_count ;increase count
parse_exit: mov command_index,si ;save SI for additional parsing
ret ;and exit
parse_line endp
;
;------------------------------------------------------------------------------
;NEXT_PARAMETER indexes SI to the next non-space character.
;Entry: DS:SI - current character | Exit: CF clear - character found
; | CF set - end-of-line reached
;------------------------------------------------------------------------------
next_parameter proc near
cmp byte ptr [si],13 ;end-of-line reached?
je end_of_line ;yes, then jump
cmp byte ptr [si],32 ;space character (delimiter)?
jne no_space ;no, then character found
inc si ;advance pointer
jmp next_parameter ;check another character
no_space: clc ;clear CF for exit
ret
end_of_line: stc ;set CF to indicate EOL
ret
next_parameter endp
;
;------------------------------------------------------------------------------
;GET_PARAMETER transfers the command line parameter indexed by SI into the
;designated buffer area, capitalizing lowercase characters in the process and
;terminating the string with a zero for ASCIIZ representation.
;Entry: DS:SI - parameter address
; ES:DI - buffer address
;------------------------------------------------------------------------------
get_parameter proc near
cmp byte ptr [si],13 ;end-of-line reached?
je end_get ;yes, then we're done
cmp byte ptr [si],32 ;space delimiter encountered?
je end_get ;yes, then we're done
lodsb ;get the character
cmp al,97 ;is it a lowercase character?
jb getparam1
cmp al,122
ja getparam1
and al,0DFh ;yes, then capitalize it
getparam1: stosb ;buffer the character
jmp get_parameter ;loop back for more
end_get: xor al,al ;zero AL
stosb ;end string with 0 delimiter
ret
get_parameter endp
;
endprog label byte ;start of buffer area
;
code ends
end begin