The preferred method of printer output is to use the handle write function (Int 21H Function 40H) with the predefined standard printer handle (4). For example, you could write the string hello to the printer as follows:
msg db 'hello' ; message for printer
msg_len equ $-msg ; length of message
.
.
.
mov ah,40h ; function 40h = write file or device
mov bx,4 ; BX = standard printer handle
mov cx,msg_len ; CX = length of string
mov dx,seg msg ; DS:DX = string address
mov ds,dx
mov dx,offset msg
int 21h ; transfer to MS-DOS
jc error ; jump if error
.
.
.
If there is no error, the function returns the carry flag cleared and the number of characters actually transferred to the list device in register AX. Under normal circumstances, this number should always be the same as the length requested and the carry flag indicating an error should never be set. However, the output will terminate early if your data contains an end-of-file mark (Ctrl-Z).
You can write independently to several list devices (for example, LPT1, LPT2) by issuing a specific open request (Int 21H Function 3DH) for each device and using the handles returned to access the printers individually with Int 21H Function 40H. You have already seen this general approach in Chapters 5 and 6.
An alternative method of printer output is to use the traditional Int 21H Function 05H, which transfers the character in the DL register to the printer. (This function is sensitive to Ctrl-C interrupts.) For example, the assembly-language code sequence at the top of the following page would write the the string hello to the line printer.
msg db 'hello' ; message for printer
msg_len equ $-msg ; length of message
.
.
.
mov bx,seg msg ; DS:BX = string address
mov ds,bx
mov bx,offset msg
mov cx,msg_len ; CX = string length
next: mov dl,[bx] ; get next character
mov ah,5 ; function 05h = printer output
int 21h ; transfer to MS-DOS
inc bx ; bump string pointer
loop next ; loop until string done
.
.
.
Programs that run on IBM PC—compatible machines can obtain improved printer throughput by bypassing MS-DOS and calling the ROM BIOS printer driver directly by means of Int 17H. Section III of this book, "IBM ROM BIOS and Mouse Functions Reference," documents the Int 17H functions in detail. Use of the ROM BIOS functions also allows your program to test whether the printer is off line or out of paper, a capability that MS-DOS does not offer.
For example, the following sequence of instructions calls the ROM BIOS printer driver to send the string hello to the line printer:
msg db 'hello' ; message for printer
msg_len equ $-msg ; length of message
.
.
.
mov bx,seg msg ; DS:BX = string address
mov ds,bx
mov bx,offset msg
mov cx,msg_len ; CX = string length
mov dx,0 ; DX = printer number
next: mov al,[bx] ; AL = character to print
mov ah,0 ; function 00h = printer output
int 17h ; transfer to ROM BIOS
inc bx ; bump string pointer
loop next ; loop until string done
.
.
.
Note that the printer numbers used by the ROM BIOS are zero-based, whereas the printer numbers in MS-DOS logical-device names are one-based. For example, ROM BIOS printer 0 corresponds to LPT1.
Finally, the most hardware-dependent technique of printer output is to access the printer controller directly. Considering the functionality already provided in MS-DOS and the IBM ROM BIOS, as well as the speeds of the devices involved, I cannot see any justification for using direct hardware control in this case. The disadvantage of introducing such extreme hardware dependence for such a low-speed device would far outweigh any small performance gains that might be obtained.