|
Table of Content | Chapter Thirteen (Part 4) |
Instruction: int 14h BIOS Operation: Access the serial communications port Parameters: ax, dx
The IBM BIOS supports up to four different serial
communications ports (the hardware supports up to eight). In general, most PCs have one or
two serial ports (COM1: and COM2:) installed. Int 14h
supports four
subfunctions- initialize, transmit a character, receive a character, and status. For all
four services, the serial port number (a value in the range 0..3) is in the dx
register
(0=COM1:, 1=COM2:, etc.). Int 14h
expects and returns other data in the al
or ax
register.
13.2.6.1 AH=0: Serial Port Initialization
Subfunction zero initializes a serial port. This call lets you set the baud rate,
select parity modes, select the number of stop bits, and the number of bits transmitted
over the serial line. These parameters are all specified by the value in the al
register
using the following bit encodings:
Bits Function 5..7 Select baud rate 000- 110 baud 001- 150 010- 300 011- 600 100- 1200 101- 2400 110- 4800 111- 9600 3..4 Select parity 00- No parity 01- Odd parity 10- No parity 11- Even parity 2 Stop bits 0-One stop bit 1-Two stop bits 0..1 Character Size 10- 7 bits 11- 8 bits
Although the standard PC serial port hardware supports 19,200 baud, some BIOSes may not support this speed.
Example: Initialize COM1: to 2400 baud, no parity, eight bit data, and two stop bits-
mov ah, 0 ;Initialize opcode mov al, 10100111b ;Parameter data. mov dx, 0 ;COM1: port. int 14h
After the call to the initialization code, the serial port
status is returned in ax
(see Serial Port Status, ah
=3, below).
13.2.6.2 AH=1: Transmit a Character to the Serial Port
This function transmits the character in the al
register
through the serial port specified in the dx
register. On return, if ah
contains
zero, then the character was transmitted properly. If bit 7 of ah
contains
one, upon return, then some sort of error occurred. The remaining seven bits contain all
the error statuses returned by the GetStatus
call except time out error
(which is returned in bit seven). If an error is reported, you should use subfunction
three to get the actual error values from the serial port hardware.
Example: Transmit a character through the COM1: port
mov dx, 0 ;Select COM1: mov al, 'a' ;Character to transmit mov ah, 1 ;Transmit opcode int 14h test ah, 80h ;Check for error jnz SerialError
This function will wait until the serial port finishes transmitting the last character (if any) and then it will store the character into the transmit register.
13.2.6.3 AH=2: Receive a Character from the Serial Port
Subfunction two is used to read a character from the serial
port. On entry, dx
contains the serial port number. On exit, al
contains
the character read from the serial port and bit seven of ah
contains the
error status. When this routine is called, it does not return to the caller until a
character is received at the serial port.
Example: Reading a character from the COM1: port
mov dx, 0 ;Select COM1: mov ah, 2 ;Receive opcode int 14h test ah, 80h ;Check for error jnz SerialError <Received character is now in AL>
13.2.6.4 AH=3: Serial Port Status
This call returns status information about the serial port
including whether or not an error has occurred, if a character has been received in the
receive buffer, if the transmit buffer is empty, and other pieces of useful information.
On entry into this routine, the dx
register contains the serial port number.
On exit, the ax
register contains the following values:
AX: Bit Meaning 15 Time out error 14 Transmitter shift register empty 13 Transmitter holding register empty 12 Break detection error 11 Framing error 10 Parity error 9 Overrun error 8 Data available 7 Receive line signal detect 6 Ring indicator 5 Data set ready (DSR) 4 Clear to send (CTS) 3 Delta receive line signal detect 2 Trailing edge ring detector 1 Delta data set ready 0 Delta clear to send
There are a couple of useful bits, not pertaining to errors, returned in this status information. If the data available bit is set (bit #8), then the serial port has received data and you should read it from the serial port. The Transmitter holding register empty bit (bit #13) tells you if the transmit operation will be delayed while waiting for the current character to be transmitted or if the next character will be immediately transmitted. By testing these two bits, you can perform other operations while waiting for the transmit register to become available or for the receive register to contain a character.
If you're interested in serial communications, you should obtain a copy of Joe Campbell's C Programmer's Guide to Serial Communications. Although written specifically for C programmers, this book contains a lot of information useful to programmers working in any programming language. See the bibliography for more details.
13.2.7 INT 15h - Miscellaneous Services
Originally, int 15h
provided cassette tape
read and write services[1]. Almost immediately, everyone
realized that cassettes were history, so IBM began using int 15h
for many
other services. Today, int 15h
is used for a wide variety of function
including accessing expanded memory, reading the joystick/game adapter card, and many,
many other operations. Except for the joystick calls, most of these services are beyond
the scope of this text. Check on the bibliography if you interested in obtaining
information on this BIOS call.
13.2.8 INT 16h - Keyboard Services
Instruction: int 16h BIOS Operation: Read a key, test for a key, or get keyboard status Parameters: al
The IBM PC BIOS provides several function calls dealing with the keyboard. As with many of the PC BIOS routines, the number of functions has increased over the years. This section describes the three calls that were available on the original IBM PC.
13.2.8.1 AH=0: Read a Key From the Keyboard
If int 16h
is called with ah
equal
to zero, the BIOS will not return control to the caller until a key is available in the
system type ahead buffer. On return, al
contains the ASCII code for the key
read from the buffer and ah
contains the keyboard scan code. Keyboard scan
codes are described in the appendices.
Certain keys on the PC's keyboard do not have any
corresponding ASCII codes. The function keys, Home, PgUp, End, PgDn, the arrow keys, and
the Alt keys are all good examples. When such a key is pressed, int 16h
returns
a zero in al
and the keyboard scan code in ah
. Therefore,
whenever an ASCII code of zero is returned, you must check the ah
register to
determine which key was pressed.
Note that reading a key from the keyboard using the BIOS int
16h
call does not echo the key pressed to the display. You have to call putc
or use int 10h
to print the character once you've read it if you want it
echoed to the screen.
Example: Read a sequence of keystrokes from the keyboard until Enter is pressed.
ReadLoop: mov ah, 0 ;Read Key opcode int 16h cmp al, 0 ;Special function? jz ReadLoop ;If so, don't echo this keystroke putc cmp al, 0dh ;Carriage return (ENTER)? jne ReadLoop
13.2.8.2 AH=1: See if a Key is Available at the Keyboard
This particular int 16h
subfunction allows you
to check to see if a key is available in the system type ahead buffer. Even if a key is
not available, control is returned (right away!) to the caller. With this call you can
occasionally poll the keyboard to see if a key is available and continue processing if a
key hasn't been pressed (as opposed to freezing up the computer until a key is pressed).
There are no input parameters to this function. On return,
the zero flag will be clear if a key is available, set if there aren't any keys in the
type ahead buffer. If a key is available, then ax
will contain the scan and
ASCII codes for that key. However, this function will not remove that keystroke from the
typeahead buffer. Subfunction #0 must be used to remove characters. The following example
demonstrates how to build a random number generator using the test keyboard function:
Example: Generating a random number while waiting for a keystroke
; First, clear any characters out of the type ahead buffer ClrBuffer: mov ah, 1 ;Is a key available? int 16h jz BufferIsClr ;If not, Discontinue flushing mov ah, 0 ;Flush this character from the int 16h ; buffer and try again. jmp ClrBuffer BufferIsClr: mov cx, 0 ;Initialize "random" number. GenRandom: inc cx mov ah, 1 ;See if a key is available yet. int 16h jz GenRandom xor cl, ch ;Randomize even more. mov ah, 0 ;Read character from buffer int 16h ; Random number is now in CL, key pressed by user is in AX
While waiting for a key, this routine is constantly
incrementing the cx
register. Since human beings cannot respond rapidly (at
least in terms of microseconds) the cl
register will overflow many times,
even for the fastest typist. As a result, cl
will contain a random value
since the user will not be able to control (to better than about 2ms) when a key is
pressed.
13.2.8.3 AH=2: Return Keyboard Shift Key Status
This function returns the state of various keys on the PC
keyboard in the al
register. The values returned are as follows:
Bit Meaning 7 Insert state (toggle by pressing INS key) 6 Caps lock (1=capslock on) 5 Num lock (1=numlock on) 4 Scroll lock (1=scroll lock on) 3 Alt (1=Alt key currently down) 2 Ctrl (1=Ctrl key currently down) 1 Left shift (1=left shift key down) 0 Right shift (1=right shift key down)
Due to a bug in the BIOS code, these bits only reflect the current status of these keys, they do not necessarily reflect the status of these keys when the next key to be read from the system type ahead buffer was depressed. In order to ensure that these status bits correspond to the state of these keys when a scan code is read from the type ahead buffer, you've got to flush the buffer, wait until a key is pressed, and then immediately check the keyboard status.
13.2.9 INT 17h - Printer Services
Instruction: int 17h BIOS Operation: Print data and test the printer status Parameters: ax, dx
Int 17h
controls the parallel printer interfaces on
the IBM PC in much the same way the int 14h
controls the serial ports. Since
programming a parallel port is considerably easier than controlling a serial port, using
the int 17h
routine is somewhat easier than using the int 14h
routines.
Int 17h
provides three subfunctions, specified
by the value in the ah
register. These subfunctions are:
0-Print the character in the AL register.
1-Initialize the printer.
2-Return the printer status.
Each of these functions is described in the following sections.
Like the serial port services, the printer port services
allow you to specify which of the three printers installed in the system you wish to use
(LPT1:, LPT2:, or LPT3:). The value in the dx
register (0..2) specifies which
printer port is to be used.
One final note- under DOS it's possible to redirect all
printer output to a serial port. This is quite useful if you're using a serial printer.
The BIOS printer services only talk to parallel printer adapters. If you need to send data
to a serial printer using BIOS, you'll have to use int 14h
to transmit the
data through a serial port.
13.2.9.1 AH=0: Print a Character
If ah
is zero when you call int 17h
,
then the BIOS will print the character in the al
register. Exactly how the
character code in the al
register is treated is entirely up to the printer
device you're using. Most printers, however, respect the printable ASCII character set and
a few control characters as well. Many printers will also print all the symbols in the
IBM/ASCII character set (including European, line drawing, and other special symbols).
Most printers treat control characters (especially ESC sequences) in completely different
manners. Therefore, if you intend to print something other than standard ASCII characters,
be forewarned that your software may not work on printers other than the brand you're
developing your software on.
Upon return from the int 17h
subfunction zero
routine, the ah
register contains the current status. The values actually
returned are described in the section on subfunction number two.
13.2.9.2 AH=1: Initialize Printer
Executing this call sends an electrical impulse to the
printer telling it to initialize itself. On return, the ah
register contains
the printer status as per function number two.
13.2.9.3 AH=2: Return Printer Status
This function call checks the printer status and returns it
in the ah
register. The values returned are:
AH: Bit Meaning 7 1=Printer busy, 0=printer not busy 6 1=Acknowledge from printer 5 1=Out of paper signal 4 1=Printer selected 3 1=I/O error 2 Not used 1 Not used 0 Time out error
Acknowledge from printer is, essentially, a redundant
signal (since printer busy/not busy gives you the same information). As long as the
printer is busy, it will not accept additional data. Therefore, calling the print
character function (ah
=0) will result in a delay.
The out of paper signal is asserted whenever the printer detects that it is out of paper. This signal is not implemented on many printer adapters. On such adapters it is always programmed to a logic zero (even if the printer is out of paper). Therefore, seeing a zero in this bit position doesn't always guarantee that there is paper in the machine. Seeing a one here, however, definitely means that your printer is out of paper.
The printer selected bit contains a one as long as the printer is on-line. If the user takes the printer off-line, then this bit will be cleared.
The I/O error bit contains a one if some general I/O error has occurred.
The time out error bit contains a one if the BIOS routine waited for an extended period of time for the printer to become "not busy" yet the printer remained busy.
Note that certain peripheral devices (other than printers)
also interface to the parallel port, often in addition to a parallel printer. Some of
these devices use the error/status signal lines to return data to the PC. The software
controlling such devices often takes over the int 17h
routine (via a
technique we'll talk about later on) and always returns a "no error" status or
"time out error" status if an error occurs on the printing device. Therefore,
you should take care not to depend too heavily on these signals changing when you make the
int 17h
BIOS calls.
Instruction: int 18h BIOS Operation: Activate ROM BASIC Parameters: None
Executing int 18h
activates the ROM BASIC
interpreter in an IBM PC. However, you shouldn't use this mechanism to run BASIC since
many PC compatibles do not have BASIC in ROM and the result of executing int 18h
is
undefined.
13.2.11 INT 19h - Reboot Computer
Instruction: int 19h BIOS Operation: Restart the system Parameters: None
Executing this interrupt has the same effect as pressing control-alt-del on the keyboard. For obvious reasons, this interrupt service should be handled carefully!
13.2.12 INT 1Ah - Real Time Clock
Instruction: int 1ah BIOS Operation: Real time clock services Parameters: ax, cx, dx
There are two services provided by this BIOS routine- read
the clock and set the clock. The PC's real time clock maintains a counter that counts the
number of 1/18ths of a second that have transpired since midnight. When you read the
clock, you get the number of "ticks" which have occurred since then. When you
set the clock, you specify the number of "ticks" which have occurred since
midnight. As usual, the particular service is selected via the value in the ah
register.
13.2.12.1 AH=0: Read the Real Time Clock
If ah
= 0, then int 1ah
returns a
33-bit value in al:cx:dx
as follows:
Reg Value Returned dx L.O. word of clock count cx H.O. word of clock count al Zero if timer has not run for more than 24 hours Non-zero otherwise.
The 32-bit value in cx:dx
represents the
number of 55 millisecond periods which have elapsed since midnight.
13.2.12.2 AH=1: Setting the Real Time Clock
This call allows you to set the current system time value. cx:dx
contains the current count (in 55ms increments) since last midnight. Cx
contains
the H.O. word, dx
contains the L.O. word.
[1] For those who do not remember that far back, before there were hard disks people used to use only floppy disks. And before there were floppy disks, people used to use cassette tapes to store programs and data. The original IBM PC was introduced in late 1981 with a cassette port. By early 1982, no one was using cassette tape for data storage.
|
Table of Content | Chapter Thirteen (Part 4) |
Chapter Thirteen: MS-DOS, PC-BIOS and
File I/O (Part 3)
28 SEP 1996