-
Notifications
You must be signed in to change notification settings - Fork 3
/
LP14.ASM
675 lines (556 loc) · 12.6 KB
/
LP14.ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
Title LP - Print File With Pagination
Page 80,132
Comment |
LP Command
________________
Purpose: To print an ASCII file on the standard printer
device at either 66 or 88 lines per page. A title
is printed at the top of each page which contains
the file name, creation date, and page number.
Syntax: LP [d][path]filename[.ext] [/6][/8]
[/L1][/L2]
[/10][/12][/17]
Remarks:
Written by Vernon Buerg for the IBM PC using
DOS 2.0 or later. For public domain use. Not
for sale or hire.
Version 1.1, April 27, 1984.
Version 1.2, Sept 12, 1984.
Version 1.4, Aug 8, 1985.
- account for TABs and long lines
- remove Int 17h due to bad spoolers
________________ |
Cseg Segment Public Para 'CODE'
Assume CS:Cseg,DS:Cseg
Org 100h
LP Proc Far
Mov SP,Offset CS:Lstack ;Use local stack
Push DS ;For DOS return
Sub AX,AX
Push AX
Mov Stk_Top,SP
Call Ver ; Check DOS version
Call Alloc ; Allocate memory
Call GetFile ; Get file name
Call Opens ; Open input
Call InitLPT ; Initialize printer
Call GetName ; Format title line
Call Titles ; and print it
Call List ; Print the file
Call Flush ; Drain the output buffer
Eod: Mov DX,Offset EofMsg ;Say END-OF-FILE
Jmp Fini
Error: Mov CS:Errlvl,1
Fini: Mov AX,CS ;Insure seg regs
Mov DS,AX
Mov SP,Stk_Top ; and stackck
Mov AH,9 ;Print error message
Int 21h
Mov BX,IHandle ;Close input
Mov AH,3Eh
Int 21h
Mov BX,OHandle ; Close output
Cmp BX,4 ; if not standard output
Je Exit
Mov AH,3Eh
Int 21h
Exit:
Mov AL,Errlvl ; Set ERROR LEVEL
Mov AH,4Ch ; and Exit
Int 21h
Page
;
; Constants and Data Areas
BEL Equ 07
BS Equ 08
TAB Equ 09
LF Equ 10
FF Equ 12
CR Equ 13
EOF Equ 1Ah
ESC Equ 1Bh
Buflen Dw 0 ;I/O buffer size (variable)
Stk_Top Dw 0 ;Stack ptr at entry
Lcnt Db 0 ;Line counter
Cpp Db 96 ;Chars per page
LPP Db 82 ;Lines per page
LPTn Dw 0 ;Printer port
Errlvl Db 0 ;Error level returned
Ccnt Db 0 ;Chars in current line
MsgIn Db CR,LF,'Enter INPUT filename $'
Msg1 Db CR,LF,'Unable to open input'
InKey Db 32,32 ;Keyboard buffer
Input Db 76 Dup (0),'$' ;Drive:path\name.ext
IHandle Dw 0 ;Input file handle
Ilen Dw 0 ;Input block length
Iptr Dw 0 ;Offset to next char
InPtr Dw 0 ;Offset to input buffer
Msg2 Db CR,LF,'Unable to open LPT'
Msg2a Db '1$'
Output Db 'LPT1:',0,'$' ;Printer name
OHandle Dw 0 ;Output file handle
Olen Dw 0 ;Output block length
Optr Dw 0 ;Offset to next char
OutPtr Dw 0 ;Offset to output buffer
OutChar Db 0
AlocMsg Db CR,LF,'Not enough memory',CR,LF,BEL,'$'
ErrMsg Db CR,LF,'Invalid command option(s)',CR,LF,BEL,'$'
Version Db 'LP - Version 1.4 - V.Buerg',CR,LF,'$'
Sorry Db 'Sorry, PC DOS 2.0 or later required',CR,LF,BEL,'$'
Heading Db CR ;Top line title
FileNm Db 43 Dup (' ')
Date Db 'mm-dd-yy',9,9
Db 'Page '
Pageno Db '1',LF
EofMsg Db CR,LF
Len_H Equ This Byte - Heading
Db 'End of File',CR,LF,'$'
Dater Record Yr:7,Mo:4,Dy:5
Reset Db CR ;Printer initialization codes
Db FF,ESC ;Form feed (no CPI setting)
Lpi Db 56 ;Lines per inch
Cpi Db 28 ;Chars per inch
Tabs Db ESC,TAB
Db '009,017,025,033,041,049,057,065,073'
Reset10 Equ $-Reset+1
Tabs12 Db ',081,089' ; When using 12-cpi
Reset12 Equ $-Reset+1
Tabs17 Db ',097,105,113,121,129',CR
Reset17 Equ $-Reset
Reset_L Dw Reset12 ; Length of initial string
Page
;
; Copy file to printer
List Proc Near
List1: Call Read ;Get one character
And AL,7FH ;Strip hi-order bit
Cmp AL,FF ;Is it form feed?
Je Eject
Cmp AL,LF ;Pass line feed
Je Passit
Cmp AL,CR ;Pass carriage return
Je Passit
Cmp AL,BS ;Pass back space
Je PassBS
Cmp AL,TAB ;Pass tab chars
Je PassTAB
Inc Ccnt ;Incr count of chars in line
Cmp AL,EOF ;End of file?
Je Done
Cmp AL,32 ;Other control char?
Jns Passit
Jmp CtlChr
PassTAB:Add Ccnt,8 ;Round up to TAB column
And Ccnt,0F8h
Jmp Passit
PassBS: Dec Ccnt ;Account for backspace
Jns Passit
Mov Ccnt,0
Passit: Call PutChar
Mov AH,Cpp ;Max chars per line
Cmp Ccnt,AH ; filled up a line?
Ja Passit2
Passit1:
Cmp AL,LF ;Is it line feed?
Jne List1 ; no, get next char
Passit2:
Inc Lcnt ; yes, incr line count
Mov Ccnt,0
Mov AL,Lcnt
Cmp AL,LPP ;End of page?
Jb List1 ; no, get next char
Eject: Mov Ccnt,0 ;Reset char count in line
Cmp Lcnt,2 ;Printed any lines yet?
Jbe List1 ; no, ignore form feed
Call NewPage
Jmp List1 ;Get next record
CtlChr: Cmp AL,0 ;Null char?
Je Blanks ; yes, make it a space
Push AX
Mov AL,'^' ;Indicate a control char
Call PutChar
Inc Ccnt
Pop AX ;Get char again
Blanks: Add AL,20H ;Make it printable
Jmp Passit
Done: Ret
List Endp
Page
;
; Process end of page
NewPage Proc Near
Cmp Lcnt,2 ;Is it title line?
Je Titles ; yes, skip rest
Mov AL,CR
Call PutChar ; no, send CR
Mov AL,FF
Call PutChar ; and form feed
Mov Lcnt,0 ;Reset line count
Push DI
Mov DI,Offset Pageno
Mov AX,3A30h
Next: Inc Byte Ptr [DI] ;Incr page number
Cmp [DI],AL ;End in zero?
Js Set1 ; yes, make it a one
Cmp [DI],AH ;Over nine?
Jne PgSet ; no, have good number
Mov [DI],AL ; yes, make last digit zero
Dec DI ; and incr hi-order
Jmp Next
Set1: Mov Byte Ptr [DI],'1'
PgSet: Pop DI
;
; Print top line titles
Titles: Mov SI,Offset Heading ;Print title line
Mov CX,Len_H
Next1: Lodsb
Cmp AL,0 ;Replace nulls
Jne Next2
Mov AL,' '
Next2: Call PutChar
Loop Next1
Mov Lcnt,2 ;Reset line counter
Ret
;
; Initialize the printer
InitLPT Proc Near ;Initialize the printer
Init1: Mov CX,Reset_L ;Length of
Mov SI,Offset Reset ; initial codes
Init2: Call Next1
Ret
InitLPT Endp
NewPage Endp
Page
;
; Format title line
GetName Proc Near ;Format title line
Mov SI,Offset Input ;Copy file name
Mov DI,Offset Filenm ; to heading
Mov CX,42 ;Max for title
Cld
Repz Movsb
Mov AX,5700h ;Return file's date and time
Mov BX,IHandle ;Input handle
Int 21h
Mov DI,Offset Date ;Date field in title
Mov AX,DX ;Get month part
And AX,Mask Mo
Mov CL,Mo
Call Format
Stosw
Inc DI ;Add delimiter
Mov AX,DX ;Get day part
And AX,Mask Dy
Mov CL,Dy
Call Format
Stosw
Inc DI ;Add delimiter
Mov AX,DX ;Get year part
And AX,Mask Yr
Mov CL,Yr
Call Format
Or AL,'8'
Stosw
Ret
GetName Endp
Format Proc Near ;Convert binary to ASCII
Shr AX,CL
Aam
Or AX,'00'
Xchg AH,AL
Ret
Format Endp
Page
;
; Extract one char from record
Read Proc Near ;Read char into AL
Read1: Cmp Ilen,0 ;Any in buffer?
Je Read2 ; no, read next block
Mov SI,Iptr ; yes, get offset in buf
Lodsb
Inc Iptr ;Offset for next one
Dec Ilen ;Decr buffer size left
Ret ; and return
Read2: Mov BX,IHandle ;Read input
Mov CX,BufLen
Mov DX,InPtr ;Set up DS:DX
Mov AH,3Fh
Int 21h ;Read a block
Mov DX,InPtr
Mov Iptr,DX ;Reset buffer ptr
Mov Ilen,AX ; and length
Jc Read8
Or AX,AX ;Anything read?
Jnz Read1 ; yes, pick it up
Mov AL,EOF ; no, return EOF
Ret
Read8: Mov DX,Offset Msg3 ;Say I/O ERROR
Jmp Error
Msg3 Db CR,LF,'I/O error',CR,LF,BEL,'$'
Read Endp
;
; Buffer characters to printer
PutChar Proc Near ;Write from AL
Mov DI,Optr ; Spot for next outchar
Stosb
Mov Optr,DI
Dec Olen ; Is it full now?
Jz PutCh0 ; yes, print the lot
Ret
Flush: Mov AX,Olen ; Bytes left in output buffer
Sub Buflen,AX ; to get count in buffer
Jnz PutCh0
Ret
PutCh0: Push AX
Push BX
Push CX
Push DX
PutCh1: Mov BX,OHandle ; Printer file handle
Mov CX,Buflen
Mov Olen,CX ; Reset size remaining in bufr
Mov DX,OutPtr
Mov Optr,DX ; Reset ptr for next put
Mov AH,40h ; Print entire buffer
Int 21h
Jc PutChe ; Successful?
Cmp AX,CX ; Wrote it all?
Je PutCh9
PutChe: Mov DX,Offset MsgPut ; Printer error
Or MsgPute,AL
Jmp Error
MsgPut Db 'Printer error -- program terminated -- RC = '
MsgPute Db '0',CR,LF,BEL,'$'
PutCh9: Pop DX
Pop CX
Pop BX
Pop AX
Ret
PutChar Endp
Page
;
; Get file names from parm
GetFile Proc Near ;Get file name(s)
Mov SI,80h ;Point to command line
Sub CX,CX ;Clear length reg
Or CL,Byte Ptr [SI] ;Get command tail length
Jz GetF8 ; none, ask for them
Mov DI,Offset Input ;Point fname target
Inc SI ;Bump command ptr
GetF1: Lodsb ;Get next char
Cmp AL,' ' ;Skip leading blanks
Jne GetF2
Loope GetF1
Jcxz GetF8 ; all blank
GetF2: Cmp AL,CR ;End of parm?
Je GetF7 ; yes, terminate fname
Cmp AL,' ' ;Delimiter?
Je GetF4 ; yes, look for swithes
Cmp AL,'/' ;Switch char?
Je GetF5
Stosb ;Save fname char
Lodsb
Loop GetF2
Jmp GetF7
GetF4: Dec CX
Jz GetF8
GetF4a: Lodsb
Cmp AL,' ' ;Skip intervening blanks
Jne GetF4b
Loope GetF4a
Jcxz GetF7 ; just trailing blanks
GetF4b: Cmp AL,CR ;End of parm?
Je GetF7 ; yes, no switches
Jmp Short GetF5b
GetF5: Dec CX
Jz GetF7
GetF5a: Lodsb
GetF5b: Cmp AL,'/' ;Switch char?
Jne GetFx ; no, invalid
Dec SI ; yes, back up to it
Call GetParm ; and set switches
GetF7:
GetF8: Cmp Input,0 ;Any input name?
Jne GetF9 ; no, ask for it
Call AskIn
GetF9: Ret
GetFx: Mov DX,Offset ErrMsg
Jmp Error
Page
;
; Determine switch parameters
GetParm Proc Near
Push DI
Push SI ;Offset to parm string
Push CX ;Length of string
Mov DI,SI ;Save string ptr
Add DI,CX ; ending offset
GetP0: Cmp SI,DI ;Any left?
Jb GetP1
Jmp GetP9 ; no, done
GetP1: Lodsb
Cmp AL,'/' ;Switch char?
Je GetP2
Jmp Short GetP0
GetP2: Cmp SI,DI ;Any string left?
Jae GetPx ; no, invalid option
GetP2a: Lodsb
Cmp AL,'L' ;Printer port?
Je GetPl
Cmp AL,'l'
Je GetPl
Cmp AL,'6' ; for 6 lpi?
Je GetP6
Cmp AL,'8' ; for 8 lpi?
Je GetP8
Cmp AL,'1' ; for cpi?
Je GetPc
GetPx: Mov DX,Offset ErrMsg ; no, say INVALID OPTIONS
Jmp Error
GetPl: Cmp SI,DI ;Have next char?
Jae GetPx
Lodsb
Cmp AL,'1' ;Valid printer?
Jb GetPx
Cmp AL,'2'
Ja GetPx
Mov Msg2a,AL ; Put 'n' into message
Mov Output+3,AL ; and into file name
Sub AL,'1' ; Form port address
Sub AH,AH
Mov LPTn,AX
Jmp GetP0 ; try next field
GetP6: Mov LPP,60 ;Set 6 lpi
Mov Lpi,54
Jmp GetP0
GetP8: Mov LPP,82 ;Set 8 lpi
Mov Lpi,56
Jmp GetP0
GetPc: Cmp SI,DI ;Any string left?
Jae GetPx ; no, invalid
Lodsb
GetPc12:
Cmp AL,'2' ;Is it 12?
Jne GetPc17
Mov Cpp,96 ; chars per line
Mov Cpi,28 ; printer control code
Mov Tabs17,CR
Mov Reset_L,Reset12
Jmp GetPc2
GetPc17:
Cmp AL,'7' ;Is it 17?
Jne GetPc10
Mov Cpp,136
Mov Cpi,29
Mov Reset_L,Reset17
Jmp GetPc2
GetPc10:
Cmp AL,'0' ;Is it 10?
Jne GetPx ; none of the above
Mov Cpp,80
Mov Cpi,30
Mov Tabs12,CR
Mov Reset_L,Reset10
GetPc2:
Jmp GetP0 ; and try next switch
GetP9: Pop CX
Pop SI
Pop DI
Ret
GetParm Endp
Page
;
; Ask for input file name
AskIn Proc Near
Ask: Mov DX,Offset MsgIn ;Prompt msg for input
Mov AH,9 ;Print string
Int 21h
Mov InKey,64
Mov DX,Offset InKey ;Ptr to keyboard buffer
Mov AH,10 ;Buffered keyboard input
Int 21h
Sub BX,BX ;Clear for insert
Add BL,InKey+1 ;Get length read
Jz Ask ;If nothing read
Mov Byte Ptr Input[BX],0 ;Set ASCIIZ stopper
Mov Word Ptr InKey,' :' ;Clear error message part
Ret
AskIn Endp
GetFile Endp
Page
;
; Open files
Opens Proc Near
Mov DX,Offset Input
Mov AX,3D00h ;Open for input
Int 21h
Jnc Openi
Mov DX,Offset Msg1
Jmp Error
Openi: Mov IHandle,AX ; Return input handle
Mov AX,4
Cmp LPTn,0 ; Using standard printer?
Je Openo
Mov DX,Offset Output ; Open LPTn
Mov AX,3D01h ; for output
Int 21h
Jnc Openo
Mov DX,Offset Msg2 ; Open failed
Jmp Error
Openo: Mov OHandle,AX ; Return output handle
Ret
Opens Endp
;
; Check DOS version
Ver Proc Near
Mov AH,30h ;Get DOS version
Int 21h
Cmp AL,2 ;Rel 2 or later?
Jae Ver1 ; if not
Mov DX,Offset Sorry
Jmp Error
Ver1: Mov DX,Offset Version
Mov AH,9 ;Display title
Int 21h
Ret
Ver Endp
Page
;
; Allocate up to 32K for read buffer
Alloc Proc Near ;Allocate storage
Mov AH,4Ah ;Modify allocated memory
Mov BX,PgmSize ;Length of Code and Stack
Int 21h
Mov BX,MaxSize ;Try for 32K each
Alloc1: Mov AH,48h
Int 21h
Jc Alloc1 ;Failed, get what there is
Sub BX,MinSize ;Safety pad
Cmp BX,MinSize ;Have enough?
Jb Alloc9
Mov DX,CS ;Get offset into DS
Sub AX,DX ; for input buffer
Mov CL,4
Shl AX,CL
Mov InPtr,AX ; Read buffer start
Mov Iptr,AX ; and current char offset
Mov OutPtr,AX ; Write buffer offset
Mov Optr,AX ; and next char offset
Shr BX,1 ; Split into two buffers
Mov CL,4 ; Convert paras
Shl BX,CL ; to bytes available
Mov Buflen,BX
Mov Olen,BX ; Bytes avail in output buffer
Add OutPtr,BX ; Re-adjust output buffer
Add Optr,BX
Ret
Alloc9: Mov DX,Offset AlocMsg
Jmp Error
Alloc Endp
LP Endp
Lstack Equ $+128 ;End of local stack
PgmSize Equ ($-Cseg+16+128)/16 ;Size of program in paragraphs
MaxSize Equ 4096-PgmSize ;Paras left in segment
MinSize Equ 32 ;Minimum buffer needed
Cseg Ends
End LP