home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
pcmag
/
vol4n08.arc
/
PR.ASM
next >
Wrap
Assembly Source File
|
1986-02-05
|
20KB
|
324 lines
;
;
CSEG segment para public 'CODE'
assume cs:cseg,ds:cseg,ss:cseg,es:cseg
org 100h ; .COM file format
BEGIN: jmp PR_MAIN ; Skip around data declarations
COPYRIGHT db 'PRint (C) 1985, Dickinson Associates Inc.'
db 13,10,'$'
VALID_IN db '/abcdefghijklmnopqrstuvwxyz,;=',9
VALID_OUT db '\ABCDEFGHIJKLMNOPQRSTUVWXYZ',4 dup(32)
VALID_NUM equ $ - VALID_OUT + 1
FN_AREA db 77 dup (0)
FN_LOC dw offset FN_AREA ; Initialize at FN_AREA
PRN equ 4 ; PC-DOS printer device handle
MAX_LINES equ 55
MAX_CHARS equ 80
FILE_HANDLE dw 0
READ_LENGTH equ 256
READ_BUFFER db READ_LENGTH dup (0),0
READ_PTR dw offset READ_BUFFER
PRINT_LENGTH equ 256
PRINT_BUFFER db PRINT_LENGTH dup (0)
PRINT_PTR dw offset PRINT_BUFFER
EOF_FOUND db 0
CHAR_COUNT dw 0
LINE_COUNT db 0
PAGE_COUNT db 0
BIN_ASC db 10
HEAD_1 db 13,10,13,10,'*',78 dup ('-'),'*',13,10
HEAD_2A db '| File: '
HEAD_2B db 70 dup (' '),'|',13,10
HEAD_3A db '| Saved: '
HEAD_3B db '00-00-00 at '
HEAD_3C db '00:00:00 '
HEAD_3D db '0m',39 dup (' '),'Page '
HEAD_3E db '00 |',13,10
HEAD_4 db '*',78 dup ('-'),'*',13,10,13,10
HEAD_LGTH dw $ - HEAD_1
ERR_HEAD db 10,13,'PRint Error - $'
NO_FILE db 'Correct Syntax is:',13,10,10
db 'PR [d:][path]filename[.ext]$'
FILE_NOT_FOUND db 'File Not Found$'
OPEN_FAILURE db 'File Open Failure$'
READ_FAILURE db 'File Read Failure$'
ERR_TAIL db 10,10,13,' . . . Aborting',10,13,13,'$'
;
PR_MAIN proc near ; PR's main program
lea dx,COPYRIGHT ; Display copyright notice
mov ah,9h ; Request display string
int 21h ; Call PC-DOS
mov si,80h ; Point SI to beginning of PSP parm area
lea di,FN_AREA ; Point SI to internal file name area
mov cl,byte ptr [si] ; Get byte count to AL
xor ch,ch ; Zero CH
jcxz NONE ; If CX is zero, no parameters passed
cld ; Set direction flag to forward
inc si ; Adjust SI to beginning of parms
mov dx,0 ; Use DX for leading blanks flag
CLEAN: lodsb ; Load each character to AL
push di ; Save DI on stack
mov di,offset VALID_IN ; Point to table of valid inputs
push cx ; Save CX on stack
mov cx,VALID_NUM ; Set CX to number of inputs to look for
repne scasb ; See if any are in AL
jcxz CLEAND ; If not, change nothing
mov bx,VALID_NUM ; Set up BX to point to valid output
sub bx,cx ; This will leave BX one off
mov al,VALID_OUT [bx - 1] ; Load the valid output (adj BX) to AL
CLEAND: pop cx ; Restore CX
pop di ; Restore DI
cmp dx,1 ; If leading blanks have been stripped,
je CLEANC ; go check for colons & other things
cmp al,' ' ; Is AL a leading blank?
je CLEANX ; Yes, ignore it & don't store it
CLEANC: mov dx,1 ; If here, leading blanks are stripped
cmp al,':' ; Is AL a colon?
je DELIM ; Yes, it's a potential FN delimiter
cmp al,'\' ; Is AL a backslash?
jne DELIMX ; Yes, it's a potential FN delimiter
DELIM: mov FN_LOC,di ; Set FN_LOC at current DI + 1
inc FN_LOC ; -- last one set will be correct
DELIMX: stosb ; Store modified AL back to PSP
CLEANX: loop CLEAN ; Loop until CX is zero
jmp FINDF ; Go see if file exists
NONE: lea dx,NO_FILE ; Exit with error if no parameter
jmp EREXIT ; passed
FINDF: mov ah,4eh ; Request find 1st file
mov cx,0 ; Set CX for normal files
lea dx,FN_AREA ; Point DX to internal file name area
int 21h ; Call PC-DOS
jnc FOUNDF ; Ok, found the 1st file
lea dx,FILE_NOT_FOUND ; If 1st file not found, exit
jmp EREXIT ; with error
FOUNDF: mov EOF_FOUND,0 ; Initialize end of file flag
mov PAGE_COUNT,0 ; Initialize page counter
mov FILE_HANDLE,0 ; Initialize file handle
mov di,FN_LOC ; DI points to end of path
mov si,9eh ; SI points to file name in default DTA
mov cx,13 ; DTA file name has 13 bytes
rep movsb ; Move bytes to FN_LOC (in FN_AREA)
mov ah,3dh ; Request open file pointed to by DX
mov al,0 ; Read permission requested
lea dx,FN_AREA ; Internal File Name Area
int 21h ; Call PC-DOS
mov FILE_HANDLE,ax ; Save File Handle contained in AX
jnc DO_PR ; No carry means successfully opened
lea dx,OPEN_FAILURE ; Open file failed, exit
jmp EREXIT ; with error message
DO_PR: call STAMP ; Set file name, date & time stamps
call PAGE_HEAD ; Print page header
mov di,PRINT_PTR ; Initialize DI to PRINT_BUFFER
PRLOOP: call READ_FILE ; Read data to buffer
jc EREXIT ; Exit if error
jcxz FINISH ; If CX is zero, end of file was reached
call PRINT ; Format and print buffered data
cmp EOF_FOUND,0 ; Was end of file flag set?
je PRLOOP ; No, keep going
FINISH: call NEW_PAGE ; Yes, print page feed
call CLOSE_FILE ; Close file
mov ah,4fh ; Request find next file
mov cx,0 ; Set CX for normal files
int 21h ; Call PC-DOS
jnc FOUNDF ; If no carry then found the next file
EXIT: ret ; If carry, exit to PC-DOS
EREXIT: push dx ; Save error message pointer on stack
mov dx,offset ERR_HEAD ; Display error header
mov ah,9 ; Request display string
int 21h ; Call PC-DOS
pop dx ; Restore error message pointer
mov ah,9 ; Request display string
int 21h ; Call PC-DOS
mov dx,offset ERR_TAIL ; Display error tail
mov ah,9 ; Request display string
int 21h ; Call PC-DOS
call CLOSE_FILE ; Close any open file
jmp EXIT ; Go exit to PC-DOS (all errors fatal)
PR_MAIN endp
;
READ_FILE proc near ; Load CX bytes to read buffer
mov bx,FILE_HANDLE ; Set BX to current File Handle
mov dx,READ_PTR ; Point DX to read buffer
mov cx,READ_LENGTH ; Set CX to read buffer length
mov ah,3fh ; Request read file
int 21h ; Call PC-DOS
jnc RD_OK ; No carry, then read was Ok
lea DX,READ_FAILURE ; Can't imagine what error occurred
jmp EX_RD ; unless coding error in file handle
RD_OK: cmp cx,ax ; If CX chars were read (noted in AX)
je NO_EOF ; then not at end of file (CF clears)
mov EOF_FOUND,1 ; Otherwise, end of file reached
NO_EOF: mov cx,ax ; Refresh CX in case end of file reached
EX_RD: ret ; Return to caller
READ_FILE endp
;
PRINT proc near ; Format and print output buffer
mov si,READ_PTR ; Set SI to read buffer
FORMAT: cmp LINE_COUNT,MAX_LINES ; Is page full?
jb LOAD ; No, go get next character
call NEW_PAGE ; Yes, print end of page / new page
call PAGE_HEAD ; Print page header
LOAD: lodsb ; Get character to AL
cmp al,26 ; Check for EOF character
je AGAIN ; Ignore it
cmp al,9 ; Is AL a Tab?
jne PUT_IT ; No, put char in print buffer
mov al,32 ; Load AL with blank to expand Tab
TAB_X: stosb ; Move AL to print buffer
inc CHAR_COUNT ; Increment line character counter
test CHAR_COUNT,7 ; Is Tab expanded? (this does mod 8)
jnz TAB_X ; No, keep loading blanks
jmp WDTH ; Go check current line width
PUT_IT: stosb ; Move AL to print buffer
inc CHAR_COUNT ; Increment line character counter
cmp al,13 ; Is AL a CR?
je AGAIN ; Yes, go force next character
cmp al,10 ; Is AL a LF?
jne FF ; No, check for Form Feed
call PRINT_LINE ; Yes, print current output buffer
jmp AGAIN ; Go get next character
FF: cmp al,12 ; Is AL a Form Feed?
jne WDTH ; No, check current width
call NEW_PAGE ; Yes, print end of page / new page
call PAGE_HEAD ; Print page header
jmp AGAIN ; Re-start loop
WDTH: cmp CHAR_COUNT,MAX_CHARS ; Is buffer full?
jb AGAIN ; No, go get next character
cmp byte ptr [si],13 ; Yes, see if CR is next character
je AGAIN ; Yes, then go get it and continue
mov ah,10 ; No, force CR,LF sequence
mov al,13 ; into print buffer
stosw ; Move AX to print buffer
add CHAR_COUNT,2 ; Add two bytes to character counter
call PRINT_LINE ; Print the line
AGAIN: loop FORMAT ; Loop bottom
ret ; Return to caller
PRINT endp
;
PRINT_LINE proc near ; Print a full or complete line
push ax ; Save affected registers
push cx ; currently in use
mov dx,PRINT_PTR ; Set DX to point to buffer
mov cx,CHAR_COUNT ; Print CHAR_COUNT characters
mov bx,PRN ; PC-DOS printer device
mov ah,40h ; Request write to device
int 21h ; Call PC-DOS - error unlikely here
mov di,PRINT_PTR ; Refresh DI
mov CHAR_COUNT,0 ; Refresh CHAR_COUNT
inc LINE_COUNT ; Increment line counter
pop cx ; Restore registers
pop ax
ret ; Return to caller
PRINT_LINE endp
;
NEW_PAGE proc near ; Print end of page / new page
cmp al,12 ; Does AL have a form feed?
je FF_OK ; Yes, so it's in the buffer
mov al,12 ; No, put one in the buffer
stosb ; Store AL in the buffer
inc CHAR_COUNT ; Increment character counter
FF_OK: call PRINT_LINE ; Print current buffer
mov LINE_COUNT,0 ; Refresh line counter
ret ; Return to caller
NEW_PAGE endp
;
PAGE_HEAD proc near ; Format and print page header
push di ; Save DI on stack
inc PAGE_COUNT ; Increase page counter
mov al,PAGE_COUNT ; Set up to convert page
lea di,HEAD_3E ; counter to ASCII
call BIN_2_ASC ; Convert to ASCII
pop di ; Restore DI
cmp HEAD_3E[0],'0' ; Does page counter have leading 0?
jne NOT_0 ; No, don't do anything to it
mov HEAD_3E[0],' ' ; Yes, make it a blank
NOT_0: push cx ; Save CX on stack
mov ah,40h ; Request write to device
mov bx,PRN ; Request PC-DOS printer device
lea dx,HEAD_1 ; Point to page header
mov cx,HEAD_LGTH ; Write all bytes in page header
int 21h ; Call PC-DOS
pop cx ; Restore CX
ret ; Return to caller
PAGE_HEAD endp
;
STAMP proc near ; Move file name, date & time stamps to page header
lea si,FN_AREA ; Internal file name
lea di,HEAD_2B ; Location of file name in page header
mov cx,70 ; Load up to 70 chars in file name field
LD_FN1: lodsb ; Get character to AL
cmp al,0 ; Is it the terminating zero?
je LD_FN2 ; Yes, go fill remainder with blanks
stosb ; No, store to page header field
loop LD_FN1 ; Loop until 0 found or CX zero
jcxz DATE ; If out of room in page header, quit
LD_FN2: mov al,32 ; Load rest of field with blanks
rep stosb
DATE: mov si,98h ; Date position in default DTA
lea di,HEAD_3B ; Month position in page header
lodsw ; Packed word field
mov bx,ax ; Make a copy in BX
and ax,01e0h ; Isolate month field
mov cl,5 ; Align to AL register
shr ax,cl ; by shifting right 5 bits
call BIN_2_ASC ; Convert binary month to ASCII
mov ax,bx ; Restore AX from BX
and ax,1fh ; Isolate day field
inc di ; Day position in page header
call BIN_2_ASC ; Convert binary day to ASCII
mov ax,bx ; Restore AX from BX
and ax,0fe00h ; Isolate year field
shr ah,1 ; Shift right to align
add ah,80 ; AH is years since 1980
mov al,ah ; Move to AL for division
inc di ; Year position in page header
call BIN_2_ASC ; Convert binary year to ASCII
TIME: mov si,96h ; Time position in default DTA
lea di,HEAD_3C ; Hours position in page header
lodsw ; Packed word field
mov bx,ax ; Make a copy in BX
and ax,0f800h ; Isolate hours field
mov cl,11 ; Align to AL register
shr ax,cl ; by shifting right 11 bits
mov HEAD_3D[0],'a' ; Assume it's an 'am' time
cmp al,12 ; Check for noon
jb AM_OK ; If less, it's AM
je PM_OK ; If equal, it's 12 PM
sub al,12 ; If more, it's after 12 PM
PM_OK: mov HEAD_3D[0],'p' ; Change 'am' to 'pm'
AM_OK: call BIN_2_ASC ; Convert binary hours to ASCII
mov ax,bx ; Restore AX from BX
and ax,7e0h ; Isolate minutes field
mov cl,5 ; Align to AL register
shr ax,cl ; by shifting right 5 bits
inc di ; Minutes position in page header
call BIN_2_ASC ; Convert binary minutes to ASCII
mov ax,bx ; Restore AX from BX
and ax,1fh ; Isolate seconds field
inc di ; Seconds position in page header
call BIN_2_ASC ; Convert binary seconds to ASCII
ret ; Return to caller
STAMP endp
;
BIN_2_ASC proc near ; Convert binary number to 2-digit ASCII
cbw ; Convert AL to word for division
div BIN_ASC ; Divide AL by BIN_ASC (contains a 10)
add al,48 ; Convert quotient (in AL) to ASCII
stosb ; Store to location pointed to by DI
add ah,48 ; Convert remainder (in AH) to ASCII
mov al,ah ; Move to AL for store
stosb ; Store to location pointed to by DI
ret ; Return to caller
BIN_2_ASC endp
;
CLOSE_FILE proc near ; Close file handle
cmp FILE_HANDLE,0 ; If 0, no file open
je CLOSEX ; Do nothing
mov bx,FILE_HANDLE ; Move file handle to BX
mov ah,3eh ; Request close file
int 21h ; Call PC-DOS
CLOSEX: ret ; Return to caller
CLOSE_FILE endp
CSEG ends
end BEGIN