Category : Files from Magazines
Archive   : VOL8N7.ZIP
Filename : LASERLST.ASM

 
Output of file : LASERLST.ASM contained in archive : VOL8N7.ZIP
PAGE 75,132
TITLE "LASERLST - List file to HP LaserJet"

CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
ORG 100H

START: JMP MAIN ; go to start of program

HEADER_MSG DB "LaserLst 1.0 (c) 1989 Ziff Communications Co.", 0DH,0AH
DB "PC Magazine",254," Michael Holmes & Bob Flanders",0DH,0AH
CRLF DB 0DH,0AH
DOLLAR DB "$"
; ---------------------------------------------------------------------------
; Initialized work areas
; ---------------------------------------------------------------------------
ARG1 DW 0 ; addr of first argument
ARG2 DW 0 ; addr of second argument
PHANDLE DW 4 ; printer handle (stdprn)
TABCOL DW 8 ; tab width
NEWPAGE DB 0 ; new page requested flag
HPSTATE DB 0 ; printer state (1 = initialized)

TITLE_ DB 1BH,"&dD" ; title line for heading
TITLE_DTE DB "mm/dd/yyyy " ; ..and display
TITLE_TME DB "hh:mm Filename: "
TITLE_FLE DB 19 dup(32)
TITLE_DSP EQU $-TITLE_DTE
DB " Page"
TITLE_PGE DB "xxxx",0dh,0ah,0ah
DB 1BH,"&d@"
TITLE_LEN EQU $-TITLE_ ; length of title
;----------------------------------------------------------------------
; DTA structure for DOS "find matching" call
;----------------------------------------------------------------------
DTA EQU 80H ; dta offset
DTA_ATTR EQU BYTE PTR DTA+21 ; file attribute
DTA_TIME EQU WORD PTR DTA_ATTR+1 ; file time
DTA_DATE EQU WORD PTR DTA_TIME+2 ; file date
DTA_LSIZ EQU WORD PTR DTA_DATE+2 ; file lsw of size
DTA_HSIZ EQU WORD PTR DTA_LSIZ+2 ; file msw of size
DTA_NAME EQU BYTE PTR DTA_HSIZ+2 ; file name of file
DTA_LEN EQU DTA_NAME+15-DTA ; length of dta find entry
;----------------------------------------------------------------------
; Messages to user
;----------------------------------------------------------------------
FILENF DB "File not found.",0DH,0AH,"$"
PRTOERR DB "Could not open output file.",0DH,0AH,"$"
FORMAT DB 0DH,0AH,"SYNTAX:",09H,"LASERLST [d:][path]filename[.ext] "
DB "[outfile] [/Tn]",0DH, 0AH, 0AH
DB " ofile defaults to LPT1:",0DH,0AH
DB " n is tab width (16 max)",0DH,0AH,"$"
;----------------------------------------------------------------------
; HP control strings
;----------------------------------------------------------------------
STRING1 DB 1BH,"E",1BH,"&l1O",1BH,"(s17H",1BH,"&l5.14C"
DB 1BH,"&l71F",1BH,"&l6E",1BH,"(s-3B"
DB 1BH,"&a0R",1BH,"&a85M",1BH,"&a5L",0DH
STRING1_LEN EQU $-STRING1

STRING2 DB 0ch,1BH,"E"
STRING2_LEN EQU $-STRING2

STRING3 DB 1BH,"&a0R",1BH,"&a90M",1BH,"&a88L",0DH,0AH,0DH,0AH
STRING3_LEN EQU $-STRING3

STRING4 DB "|", 0DH,0AH

STRING5 DB 1BH,"&a0R",1BH,"&a171M",1BH,"&a91L",0DH
STRING5_LEN EQU $-STRING5

STRING6 DB 0CH,1BH,"&a0R",1BH,"&a85M",1BH,"&a5L",0DH
STRING6_LEN EQU $-STRING6
; ---------------------------------------------------------------------------
; MAIN - Mainline of program
; ---------------------------------------------------------------------------
MAIN PROC ; start of program

CALL INIT ; initialize program

MAIN10: CALL OPEN ; open the input file
JC MAIN80 ; if we can't .. try next

MAIN20: CALL READ ; read a block

CALL PRINT ; print the line

OR SI, SI ; q. end of file?
JNZ MAIN20 ; a. no .. get next line

MOV BX, FHANDLE ; bx = input file handle
MOV AH, 3EH ; ah = close file
INT 21H ; .. ask DOS to do it

MAIN80: MOV AH, 4FH ; ah = find next file
INT 21H ; q. file found?
JNC MAIN10 ; a. yes .. continue

MOV DX, OFFSET DOLLAR ; dx -> null message
CALL DIE ; .. say goodnight

MAIN ENDP
; ---------------------------------------------------------------------------
; INIT - Handle initialization
; ---------------------------------------------------------------------------
INIT PROC

CLD ; assure ascending
MOV AH, 19H ; ah = get current drive
INT 21H ; al = current drive
MOV EDRV, AL ; save entry drive

MOV SI, OFFSET EDIR ; si -> current directory area
MOV BYTE PTR [SI], '\' ; .. start with backslash
INC SI ; si -> next byte
XOR DL, DL ; dl = default drive
MOV AH, 47H ; ah = get current dir
INT 21H ; .. save in area

MOV DX, OFFSET HEADER_MSG ; dx -> header message
MOV AH, 9 ; ah = print ascii$ message
INT 21H ; .. ask DOS to do it

CALL PARMS ; check parameters

CMP ARG2, 0 ; q. arg2 specified?
JE INIT20 ; a. yes .. skip open

MOV DX, ARG2 ; dx -> arg2 value
MOV AH, 3CH ; ah = create file
XOR CX, CX ; .. cx = file attributes
INT 21H ; q. open the file ok?
JNC INIT10 ; a. yes .. continue

MOV DX, OFFSET PRTOERR ; dx -> open error message
CALL DIE ; .. you're dead, Jim.

INIT10: MOV PHANDLE, AX ; save printer handle

INIT20: CALL DFLPATH ; set up dir & drive

MOV AH, 4EH ; ah = find first
MOV DX, OFFSET FILENAME ; dx -> file to find
XOR CX, CX ; cx = search attribute
INT 21H ; q. find first file ok?
JNC INIT90 ; a. yes .. continue

MOV DX, OFFSET FILENF ; dx -> file not found
CALL DIE ; .. gasp you're final breath

INIT90: RET ; return to caller

INIT ENDP
; ---------------------------------------------------------------------------
; OPEN - Opens the next file to process and update title line
; Exit: Carry indicates file would not open.
; ---------------------------------------------------------------------------
OPEN PROC

MOV DX, OFFSET DTA_NAME ; dx -> file name
MOV AX, 3D00H ; al = open for read
INT 21H ; .. ask DOS to do it.
JNC OPEN05 ; ok .. continue

RET ; else .. return if error

OPEN05: MOV FHANDLE, AX ; save file handle
MOV LASTBUFF, 0 ; show last buffer not read

MOV SI, OFFSET DTA_NAME ; si -> file name
MOV DI, OFFSET TITLE_FLE ; di -> file name area
PUSH DI ; .. save it
MOV AL, ' ' ; al = blank
MOV CX, 15 ; .. amount to blank
REP STOSB ; .. clear the file name
POP DI ; .. restore output pointer

OPEN10: LODSB ; al = byte from file name

OR AL, AL ; q. end of name?
JZ OPEN20 ; a. yes .. end loop

STOSB ; store a byte
JMP OPEN10 ; .. and move next

OPEN20: MOV BL, '0' ; fill value
MOV AX, DS:DTA_DATE ; ax = date field
PUSH AX ; save for later
PUSH AX ; .. again

MOV CL, 5 ; cl = shift value
SHR AX, CL ; .. mm to lower bits
AND AX, 0FH ; .. upper bits off
MOV CX, 2 ; cx = number of characters
MOV DI, OFFSET TITLE_DTE ; di -> mm
CALL ITOA ; .. move in mm

POP AX ; ax = date
AND AX, 1FH ; al = dd
MOV CX, 2 ; cx = number of chars
MOV DI, OFFSET TITLE_DTE+3 ; di -> dd
CALL ITOA ; .. move into dd

POP AX ; ax = date
MOV CL, 9 ; cl = shift amount
SHR AX, CL ; .. ax = yy
ADD AX, 1980 ; ax = year
MOV CX, 4 ; cx = length of output
MOV DI, OFFSET TITLE_DTE+6 ; di -> yyyy
CALL ITOA ; .. move into yyyy

MOV AX, DS:DTA_TIME ; ax = time
PUSH AX ; .. save for later
MOV CL, 11 ; cl = shift value
SHR AX, CL ; .. ax = hh
MOV CX, 2 ; cx = length of output
MOV DI, OFFSET TITLE_TME ; di -> hh
CALL ITOA ; .. move into hh

POP AX ; ax = time
MOV CL, 5 ; cl = shift value
SHR AX, CL ; ax = mm
AND AX, 3FH ; .. upper bits off
MOV CX, 2 ; cx = length of output
MOV DI, OFFSET TITLE_TME+3 ; di -> mm
CALL ITOA ; .. move into mm

MOV AH, 40H ; ah = write to device
MOV BX, 1 ; bx = stdout device
MOV CX, TITLE_DSP ; cx = length to display
MOV DX, OFFSET TITLE_DTE ; dx -> part of header line
INT 21H ; issue dos call

MOV AH, 40H ; ah = write to device
MOV BX, 1 ; bx = stdout device
MOV CX, 2 ; cx = length to display
MOV DX, OFFSET CRLF ; dx -> string
INT 21H ; issue dos call

CLC ; show all went ok
OPEN90: RET

OPEN ENDP
; ---------------------------------------------------------------------------
; READ - Read the next buffer full
; Exit: si -> next line, 0 if eof, cx = length of line
; ---------------------------------------------------------------------------
READ PROC

PUSH AX ; save registers
PUSH BX
PUSH DX

MOV SI, 0 ; si -> nothing

CMP LASTBUFF, 1 ; q. last buffer have 1ah?
JE READ90 ; a. yes .. end it all

MOV AH, 03FH ; ah = read file
MOV BX, FHANDLE ; bx = handle of file to read
MOV CX, BUFLEN ; cx = amount to read
MOV DX, OFFSET BUFFER ; dx -> buffer
INT 21H ; read, please
JC READ90 ; error .. return eof

OR AX, AX ; q. any read?
JZ READ90 ; a. yes .. return with something

MOV SI, OFFSET BUFFER ; si -> start of line
MOV CX, AX ; cx = nbr of characters read
MOV BX, AX ; .. and bx

MOV DI, SI ; di -> chars read
MOV AL, 1AH ; al = EOF indicator

REPNE SCASB ; q. eof found?
JNE READ80 ; a. no .. continue

INC CX ; .. increment count
NEG CX ; .. and negate it
MOV LASTBUFF, 1 ; .. and set lastbuff flag

READ80: ADD CX, BX ; q. any bytes this buffer?
JNZ READ90 ; a. yes .. continue

MOV SI, 0 ; a. else .. show end of file.

READ90: POP DX ; restore registers
POP BX ;
POP AX ;
RET ; ..and return to caller

READ ENDP
; ---------------------------------------------------------------------------
; PRINT - Print requested data
; Entry: si -> string to print or 0, cx = length of input string
; ---------------------------------------------------------------------------
PRINT PROC

OR SI, SI ; q. end of file call?
JNE PRINT10 ; a. no .. continue

CALL EPILOGUE ; put out trailing characters
RET ; ..and return to caller

PRINT10: PUSH AX ; save registers
PUSH BX
PUSH CX
PUSH DX
PUSH SI

CMP HPSTATE, 0 ; q. initial state?
JNE PRINT20 ; a. no .. continue

CALL PROLOGUE ; send out initial string

PRINT20: CALL EXPAND ; handle tab expansion
MOV DX, SI ; dx -> start of new buffer
MOV BX, CX ; bx = nbr of chars in buffer
XOR CX, CX ; cx = nbr of chars to print
MOV AH, USEDLEN ; ah = printed chars in this line

PRINT30: LODSB ; al = first character

CMP AL, 0CH ; q. formfeed?
JNE PRINT40 ; a. yes .. process it

CALL LINEPRT ; print the line
CALL PAGEBREAK ; do a page break
XOR AH, AH ; ah = nbr of columns used
DEC BX ; bx = decrement remaining count
INC DX ; dx -> next printable character
JMP PRINT70 ; ..and continue w/common code

PRINT40: CMP AL, 0AH ; q. linefeed?
JNE PRINT50 ; a. no .. continue

DEC BX ; bx = remaining chars in buffer
INC CX ; cx = nbr of characters to print
CALL LINEPRT ; print the line
XOR AH, AH ; ah = nbr of columns used
CALL BUMPLINE ; increment/test line counter
JMP PRINT70 ; ..and continue w/common code

PRINT50: CMP AL, 0DH ; q. carriage return?
JNE PRINT55 ; a. no .. continue
JMP SHORT PRINT57 ; ..and continue w/common code

PRINT55: CMP AL, 08H ; q. BackSpace?
JNE PRINT60 ; a. no .. continue

DEC AH ; move back a column
JNS PRINT65 ; .. but not beyond first

PRINT57: XOR AH, AH ; ah = start of line
JMP SHORT PRINT65 ; .. and continue

PRINT60: INC AH ; increment nbr of columns used
PRINT65: INC CX ; ..and nbr of chars to print
DEC BX ; decrement remaining char count

CMP AH, 81 ; q. reached end of line?
JL PRINT70 ; a. no .. continue

CALL LINEPRT ; print upto page width
PUSH CX ; save registers
PUSH DX ;
MOV DX, OFFSET CRLF ; dx ->
MOV CX, 2 ; cx = string length
CALL WRITE ; print the crlf to do line wrapping
POP DX ; restore registers
POP CX ;
XOR AH, AH ; ah = nbr of columns used
CALL BUMPLINE ; increment/test line counter

PRINT70: OR BX, BX ; q. anything left to check?
JNZ PRINT30 ; a. yes .. loop till done

CALL LINEPRT ; print the line
MOV USEDLEN, AH ; save nbr of columns used

POP SI ; restore registers
POP DX ;
POP CX ;
POP BX ;
POP AX ;
RET ; ..and return to caller

PRINT ENDP
; ---------------------------------------------------------------------------
; DIE - Display an error message and return to DOS
; Entry: dx -> error message ended in dollar sign.
; ---------------------------------------------------------------------------
DIE PROC

MOV AH, 9 ; ah = print string
INT 21H ; .. call dos to print error

MOV DL, EDRV ; dl = drive to select
MOV AH, 0EH ; ah = select drive
INT 21H ; .. select the drive

MOV DX, OFFSET EDIR ; dx -> directory
MOV AH, 3BH ; ah = CHDIR request
INT 21H ; .. ask DOS to do it

MOV AX, 4C00H ; ax = exit
INT 21H ; .. terminate routine

DIE ENDP
; ---------------------------------------------------------------------------
; PARMS - Parses the command line
; ---------------------------------------------------------------------------
PARMS PROC

CALL UPCASE ; upper case the parm area
MOV SI, 81H ; si -> parms area

PARMS10: LODSB ; get parameter character

CMP AL, '/' ; q. option?
JE PARMS80 ; a. yes .. check option
CMP AL, 0DH ; q. end of line?
JE PARMS50 ; a. yes .. exit
CMP AL, ' ' ; q. blank?
JNA PARMS10 ; a. yes .. skip
CALL ARG ; set the argument
JC PARMSERR ; .. die on an error

PARMS30: LODSB ; get next character
CMP AL, 0DH ; q. end of line?
JE PARMS50 ; a. yes .. process
CMP AL, '/' ; q. start of option?
JE PARMS80 ; a. yes .. process
CMP AL, ' ' ; q. end of PARMS?
JA PARMS30 ; a. no .. next char

CALL ENDPARM ; terminate parm string
JMP PARMS10 ; .. look for next

PARMS50: CALL ENDPARM ; terminate parm string

CMP ARG1, 0 ; q. PARMS 1 available?
JE PARMSERR ; a. no .. error
RET ; .. else .. return to caller

PARMS80: CALL ENDPARM ; terminate parm string
LODSB ; al = option character

CMP AL, 'T' ; q. Tab width?
JNE PARMSERR ; a. no .. error in option

CALL ATOI ; ax = tab width

CMP AX, 16 ; q. request greater than max?
JG PARMS10 ; a. yes .. unreasonable

MOV TABCOL, AX ; .. save tab width
JMP PARMS10 ; .. continue scan

PARMSERR: MOV DX, OFFSET FORMAT ; dx -> format message
CALL DIE ; abort

PARMS ENDP
; ---------------------------------------------------------------------------
; ARG - Setup pointers to the command line arguments
; Entry: si -> second character in argument.
; Exit: ARG1 or ARG2 pointers filled in.
; Carry set if more than 2 arguments detected.
; ---------------------------------------------------------------------------
ARG PROC

LEA BX, [SI-1] ; bx -> argument
CMP ARG1, 0 ; q. arg1 filled in?
JNE ARG10 ; a. yes .. check 2
MOV ARG1, BX ; save arg1 pointer
JMP SHORT ARG90 ; .. exit ok!

ARG10: CMP ARG2, 0 ; q. arg2 filled in?
JE ARG20 ; a. no .. fill it in
STC ; else .. error
RET ; .. and return to caller

ARG20: MOV ARG2, BX ; save arg2 pointer
ARG90: CLC ; show no error
RET ; return to caller

ARG ENDP
; ---------------------------------------------------------------------------
; ENDPARM - Handle parameters which end in a colon
; Entry: si -> first character past end of parameter
; ---------------------------------------------------------------------------
ENDPARM PROC

CMP BYTE PTR [SI-2], ':' ; q. argument end in a colon?
JNE ENDPARM10 ; a. no .. continue

MOV BYTE PTR [SI-2], 0 ; ..it doesn't any more
RET ; ..and return

ENDPARM10: MOV BYTE PTR [SI-1], 0 ; end the parameter
RET ; ..and return

ENDPARM ENDP
; ---------------------------------------------------------------------------
; DFLPATH - Setup the default drive and path
; ---------------------------------------------------------------------------
DFLPATH PROC

MOV DI, ARG1 ; di -> first arg

DFLPATH10: CMP BYTE PTR [DI+1], ':' ; q. drive specified?
JNE DFLPATH20 ; a. no .. use current drive
MOV DL, [DI] ; dl = drive to use
SUB DL, 'A' ; get requested drive number
MOV AH, 0EH ; set requested drive
INT 21H ; .. via dos
ADD DI, 2 ; di -> next part

DFLPATH20: PUSH DI ; save pointer
MOV BX, DI ; bx -> start of area
XOR AL, AL ; al = search for null
MOV CX, 128 ; very max to search
CLD
REPNE SCASB ; find end of arg
LEA SI, [DI-1] ; si -> nul
MOV CX, 0 ; cx = # chars to move
CMP SI, BX ; q. any file name
JE DFLPATH80 ; a. no .. error

DFLPATH30: DEC SI ; si -> prev char
CMP BYTE PTR [SI], '\' ; q. dir?
JE DFLPATH35 ; a. yes .. end of file name.
INC CX ; cx = char count
CMP SI, BX ; q. done?
JE DFLPATH37 ; a. yes .. move file name
JMP DFLPATH30 ; .. continue

DFLPATH35: INC SI ; si -> start of file name
DFLPATH37: OR CX, CX ; q. file name spec'd?
JZ DFLPATH80 ; a. no .. error
CMP CX, 12 ; q. too long?
JA DFLPATH85 ; a. yes .. error
PUSH SI ; save start pointer
MOV DI, OFFSET FILENAME ; di -> file name
INC CX ; .. assure nul moves too
REP MOVSB ; .. move in the file name
POP SI ; restore start pointer
POP DI ; .. and dir pointer
CMP SI, BX ; q. at start of parm?
JE DFLPATH90 ; a. yes .. return
INC BX ; bx -> next char
CMP SI, BX ; q. root only given?
JE DFLPATH40 ; a. yes .. continue
DEC SI ; si -> last \

DFLPATH40: MOV BYTE PTR [SI], 0 ; make dir ASCIIZ
DFLPATH50: MOV DX, DI ; dx -> directory
MOV AH, 3BH ; ah = CHDIR opcode
INT 21H ; .. change directory
JNC DFLPATH90 ; if ok .. continue
JMP SHORT DFLPATH85 ; dx -> baddir request

DFLPATH80: MOV DX, OFFSET FORMAT ; dx -> no file specified
CALL DIE

DFLPATH85: MOV DX, OFFSET FILENF ; dx -> invalid filename spec'd
CALL DIE

DFLPATH90: RET ; return to caller

DFLPATH ENDP
; ---------------------------------------------------------------------------
; EXPAND - Handle tab expansion
; Entry:
; si -> line read from file ended by a linefeed
; cx = length of line
; Exit:
; si -> reformatted line in output buffer
; cx = new line length
; ---------------------------------------------------------------------------
EXPAND PROC

PUSH AX ; save registers
PUSH BX
PUSH DX
PUSH DI

MOV DI, OFFSET OBUFF ; di -> start of output buffer

EXPAND10: LODSB ; al = character from input line

CMP AL, 09H ; q. tab character?
JNE EXPAND30 ; a. no .. continue processing

MOV AX, CURCOL ; ax = current column
DEC AX ; ax = column offset
XOR DX, DX ; dx:ax = current column
MOV BX, TABCOL ; bx = nbr of columns per tab
IDIV BX ; dx = space within tab stop

SUB BX, DX ; bx = spaces left in tab stop

MOV AL, 20H ; al = space char to padding string

EXPAND20: STOSB ; put a blank in output buffer
INC CURCOL ; bump current column nbr

DEC BX ; q. done yet?
JNZ EXPAND20 ; a. no .. keep looping
JMP SHORT EXPAND50 ; a. yes .. get next character

EXPAND30: CMP AL, 0DH ; q. carriage return?
JE EXPAND33 ; a. yes .. reset column

CMP AL, 0CH ; q. form feed?
JNE EXPAND35 ; a. no .. continue processing

EXPAND33: MOV CURCOL, 0 ; setup for start of new line
JMP SHORT EXPAND40 ; .. continue

EXPAND35: CMP AL, 08H ; q. backspace?
JNE EXPAND40 ; a. no .. continue

STOSB ; save the BS
DEC CURCOL ; .. move back a space
JNZ EXPAND50 ; .. get next character

MOV CURCOL, 1 ; init current column
JMP SHORT EXPAND50 ; .. continue

EXPAND40: STOSB ; move character to output line
CMP AL, 0AH ; q. line feed?
JE EXPAND50 ; a. yes .. don't count it

INC CURCOL ; bump current column nbr

EXPAND50: LOOP EXPAND10 ; ..loop till input exhausted

MOV SI, OFFSET OBUFF ; si -> start of output buffer
MOV CX, DI ; di -> just past last char of output
SUB CX, SI ; cx = nbr of characters in output

POP DI ; restore registers
POP DX
POP BX
POP AX
RET ; ..and return to caller

EXPAND ENDP
; ---------------------------------------------------------------------------
; LINEPRT - Handle printing a line
; Entry:
; dx -> start of line
; cx = nbr of characters to print
; Exit:
; dx -> start of next line
; cx = 0
; ---------------------------------------------------------------------------
LINEPRT PROC

JCXZ LINEPRT90 ; if nothing to print.. return

CMP NEWPAGE, 1 ; q. need a new page?
JNE LINEPRT10 ; a. no .. continue

CALL PAGEBREAK ; else .. do a pagebreak

LINEPRT10: CALL WRITE ; write the line

ADD DX, CX ; dx -> start of next line
XOR CX, CX ; cx = nbr of characters to print
LINEPRT90: RET

LINEPRT ENDP
; ---------------------------------------------------------------------------
; MKTITLE - Make the title line be ready to print
; Exit:
; dx -> title line
; cx = title line length
; ---------------------------------------------------------------------------
MKTITLE PROC
PUSH AX ; save registers
PUSH BX
PUSH DI

MOV AX, PAGENO ; ax = page number
MOV CX, 4 ; cx = length of output
MOV BL, ' ' ; bl = fill char (blank)
MOV DI, OFFSET TITLE_PGE ; di -> output area
CALL ITOA ; .. fill in page number

MOV DX, OFFSET TITLE_ ; dx -> title
MOV CX, TITLE_LEN ; cx = length of title
CALL WRITE ; print title line

POP DI ; restore registers
POP BX
POP AX
RET ; return to caller

MKTITLE ENDP
; ---------------------------------------------------------------------------
; PAGEBREAK - Handle page overflow condition
; ---------------------------------------------------------------------------
PAGEBREAK PROC

PUSH BX ; save registers
PUSH CX
PUSH DX

TEST PAGENO, 1 ; q. finishing up with left page?
JZ PAGEBRK20 ; a. no .. do other page

MOV DX, OFFSET STRING3 ; dx -> get to right page string
MOV CX, STRING3_LEN ; cx = length
CALL WRITE ; write out 1st part of string

MOV BX, 66 ; bx = loop count
MOV CX, 3 ; cx = nbr of chars to print
MOV DX, OFFSET STRING4 ; dx -> vertical bar string

PAGEBRK10: CALL WRITE ; write on line of vertical bars

DEC BX ; q. done yet?
JNZ PAGEBRK10 ; a. no .. keep looping

MOV DX, OFFSET STRING5 ; dx -> string to finish up
MOV CX, STRING5_LEN ; cx = length
JMP PAGEBRK30 ; ..and continue w/common code

PAGEBRK20: MOV DX, OFFSET STRING6 ; dx -> get to left page string
MOV CX, STRING6_LEN ; cx = length

PAGEBRK30: CALL WRITE ; print the init line

MOV LINECNT, 1 ; reset line counter
MOV NEWPAGE, 0 ; clear new page request flag
INC PAGENO ; ..and bump page number

CALL MKTITLE ; print title line

POP DX ; restore registers
POP CX ;
POP BX ;
RET ; ..and return to caller

PAGEBREAK ENDP
; ---------------------------------------------------------------------------
; BUMPLINE - Increment line counter and test for overflow
; ---------------------------------------------------------------------------
BUMPLINE PROC
INC LINECNT ; increment line counter

CMP LINECNT, 66 ; q. reached max lines/page?
JLE BUMPLINE90 ; a. no .. continue

MOV NEWPAGE, 1 ; else .. show we'll need a new one

BUMPLINE90: RET ; ..then return to caller

BUMPLINE ENDP
; ---------------------------------------------------------------------------
; PROLOGUE - Put out laserjet initialization string
; ---------------------------------------------------------------------------
PROLOGUE PROC

PUSH CX ; save registers
PUSH DX

MOV DX, OFFSET STRING1 ; dx -> initialization string
MOV CX, STRING1_LEN ; cx = length
CALL WRITE ; print the init line

MOV PAGENO, 1 ; setup page number
MOV CURCOL, 1 ; ..and current column number
MOV LINECNT, 1 ; ..and line counter
MOV HPSTATE, 1 ; ..show in left page
MOV USEDLEN, 0 ; ..clear column position
CALL MKTITLE ; print title line

POP DX ; restore registers
POP CX ;
RET ; ..and return to caller

PROLOGUE ENDP
; ---------------------------------------------------------------------------
; EPILOGUE - Put out laserjet finish up string
; ---------------------------------------------------------------------------
EPILOGUE PROC

PUSH CX ; save registers
PUSH DX

MOV DX, OFFSET STRING2 ; dx -> termination string
MOV CX, STRING2_LEN ; cx = length
CALL WRITE ; print the init line

MOV HPSTATE, 0 ; show back to initialization state

POP DX ; restore registers
POP CX ;
RET ; ..and return to caller

EPILOGUE ENDP
; ---------------------------------------------------------------------------
; WRITE - Send a string to the printer
; Entry:
; dx -> string to write
; cx = nbr of characters
; ---------------------------------------------------------------------------
WRITE PROC

PUSH AX ; save registers
PUSH BX

MOV AH, 40H ; ah = write to file/device function
MOV BX, PHANDLE ; bx = printer handle
INT 21H ; issue dos call

POP BX ; restore registers
POP AX ;
RET ; ..and return to caller

WRITE ENDP
; ---------------------------------------------------------------------------
; UPCASE - Convert command line arguments to uppercase
; ---------------------------------------------------------------------------
UPCASE PROC

PUSH SI ; save caller regs
PUSH DI
MOV SI, 81H ; si -> start of parm area
MOV DI, SI ; .. same for di
CLD ; .. assure ascending

UPCASE10: LODSB ; al = char
CMP AL, 0DH ; q. end of line?
JE UPCASE90 ; a. yes .. end of line!
CMP AL, 'a' ; q. is it below 'a'?
JB UPCASE20 ; a. yes .. continue
CMP AL, 'z' ; q. is it above 'z'?
JA UPCASE20 ; a. yes .. continue
SUB AL, 20H ; set to upper case

UPCASE20: STOSB ; save the byte
JMP UPCASE10 ; .. and continue

UPCASE90: POP DI ; restore caller regs
POP SI
RET ; .. and return to caller

UPCASE ENDP
; ---------------------------------------------------------------------------
; ATOI - Translate an ascii value to binary
; Entry:
; si -> ascii value
; Exit:
; al = binary value
; ---------------------------------------------------------------------------
ATOI PROC

XOR AX, AX ; ax = accumulator = 0

ATOI10: CMP BYTE PTR [SI], '0' ; q. below ascii 0?
JB ATOI90 ; a. yes.. exit

CMP BYTE PTR [SI], '9' ; q. above ascii 9?
JA ATOI90 ; a. yes.. exit

XOR AH, AH ; reset ah
MOV BL, 10 ; bl = multiply value
MUL BL ; .. multiply by 10
MOV BL, [SI] ; bl = value
AND BL, 0FH ; .. upper bits off
ADD AL, BL ; .. add to bl

INC SI ; si -> next char
JMP ATOI10 ; .. tranlate it

ATOI90: RET ; .. return to caller

ATOI ENDP
; ---------------------------------------------------------------------------
; ITOA - Integer to ASCII characters
; Entry:
; ax = value to convert
; bl = fill character
; cx = nbr of characters
; di -> start of alpha area
; ---------------------------------------------------------------------------
ITOA PROC

PUSH AX ; save registers
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSHF
STD ; ..and set direction flag

ADD DI, CX ; di -> 1st char past work area
DEC DI ; di -> last char in work area
PUSH BX ; save fill character
MOV BX, 10 ; bx = divisor

ITOA10: OR AX, AX ; q. any value to convert?
JZ ITOA20 ; a. no .. exit loop

XOR DX, DX ; dx:ax = value to divide
IDIV BX ; ax = dividend, dx = remainder
OR DL, 30H ; dl = ASCII number
MOV [DI], DL ; store character in buffer
DEC DI ; di -> next output char location

DEC CX ; q. any more room in buffer?
JNZ ITOA10 ; a. yes .. continue loop

POP BX ; restore register
JMP ITOA90 ; ..and exit through common code

ITOA20: POP AX ; al = fill character

ITOA30: STOSB ; store fill character

DEC CX ; q. any more room in buffer?
JNZ ITOA30 ; a. yes .. continue loop

ITOA90: POPF ; restore flags
POP DI ; ..and registers
POP DX ;
POP CX ;
POP BX ;
POP AX ;
RET ; ..and return

ITOA ENDP
; ---------------------------------------------------------------------------
; Uninitialized data areas
; ---------------------------------------------------------------------------
UDATA EQU $ ; start of unitialized data
PAGENO EQU WORD PTR UDATA ; current page number
CURCOL EQU WORD PTR PAGENO+2 ; current column
LINECNT EQU WORD PTR CURCOL+2 ; line count
EDRV EQU BYTE PTR LINECNT+2 ; current disk
EDIR EQU BYTE PTR EDRV+1 ; current directory
FILENAME EQU BYTE PTR EDIR+65 ; filename specifed as ARG1
LASTBUFF EQU BYTE PTR FILENAME+13 ; last buffer indicator
FHANDLE EQU WORD PTR LASTBUFF+1 ; input file handle
BUFFER EQU BYTE PTR FHANDLE+2 ; file buffer
BUFLEN EQU 2048 ; length of buffer
USEDLEN EQU BYTE PTR BUFFER+BUFLEN ; used length in a logical line
OBUFF EQU BYTE PTR USEDLEN+1 ; output buffer - must be last!

CSEG ENDS ; end of code segment
END START


  3 Responses to “Category : Files from Magazines
Archive   : VOL8N7.ZIP
Filename : LASERLST.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/