Sie sind auf Seite 1von 42

BIOS and DOS Interrupts

Dr. Tim McGuire


CS 272
Sam Houston State University

• These notes roughly correspond to text chapter 10, although the approach is
considerably different

Overview

• Previously, we used the INT (interrupt) instruction to call system routines


• In this module, we discuss different kinds of interrupts and take a closer look at the
operation of the INT instruction
o We will discuss the services provided by various BIOS (basic input/output
system) and DOS interrupt routines
• To demonstrate the use of interrupts, we will write a program that displays the
current time on the screen

Hardware Interrupt

• Whenever a key is pressed, the CPU must be notified to read a key code into the
keyboard buffer
• The general hardware interrupt goes like this:
• a device that needs service sends an interrupt request signal to the processor
o the CPU suspends the current task and transfers control to an interrupt
routine
o the interrupt routine services the hardware device by performing some I/O
operation
o control is transferred back to the original executing task at the point where it
was suspended

Questions to be Answered

• How does the CPU find out a device is signaling?


• How does it know which interrupt routine to execute?
• How does it resume the previous task?

Acknowledging an Interrupt

• Because an interrupt signal may come at any time, the CPU checks for the signal
after executing each instruction
• On detecting the interrupt signal, the CPU acknowledges it by sending an interrupt
acknowledge signal
• The interrupting device responds by sending an eight-bit number on the data bus,
called an interrupt number
• Each device uses a different interrupt number to identify its own service routine
• This process is called hand-shaking

Transferring to an Interrupt Routine

• The process is similar to a procedure call


• Before transferring control to the interrupt routine, the CPU first saves the address
of the next instruction on the stack; this is the return address
• The CPU also saves the FLAGS register on the stack; this ensures that the status of
the suspended task will be restored
• It is the responsibility of the interrupt routine to restore any registers it uses

Software Interrupt

• Software interrupts are used by programs to request system services


• A software interrupt occurs when a program calls an interrupt routine using the
INT instruction
• The format of the INT instruction is

INT interrupt_number

• The 8086 treats this interrupt number in the same way as the interrupt number
generated by a hardware device
• We have already seen a number of examples of this using INT 21h and INT 10h

Processor Exception

• There is a third kind of interrupt, called a processor exception


• A processor exception occurs when a condition arises inside the processor, such as
divide overflow, that requires special handling
• Each condition corresponds to a unique interrupt type
• For example, divide overflow is type 0, so when overflow occurs in a divide
instruction the CPU automatically executes interrupt 0 to handle the overflow
condition

Interrupt Numbers

• The interrupt numbers for the 8086 are unsigned byte values -- therefore 256 types
of interrupts are possible
• Not all interrupt numbers are used
• BIOS interrupt service routines are stored in ROM
• DOS interrupt routines (int 21h) are loaded into memory when the machine is
started
• Some additional interrupt numbers are reserved by the manufacturer for further use;
the remaining numbers are available for the user

Interrupt Types
Interrupt Types Description

0h-1Fh BIOS Interrupts


20h-3Fh DOS Interrupts
40h-7Fh reserved
80h-F0h ROM BASIC
F1h-FFh not used

Interrupt Vector

• The CPU does not generate the interrupt routine's address directly from the interrupt
number
o Doing so would mean that a particular interrupt routine must be placed in
exactly the same location in every computer
o Instead, the CPU uses the interrupt number to calculate the address of a
memory location that contains the actual address of the interrupt routine
• This means that the routine may appear anywhere, so long as its address, called an
interrupt vector, is stored in a predefined memory location

Interrupt Vector Table

• All interrupt vectors are placed in an interrupt vector table, which occupies the first
1KB of memory
• Each interrupt vector is given as segment:offset and occupies four bytes
o The first four bytes of memory contain interrupt vector 0

Accessing the Vector

• To find the vector for an interrupt routine, multiply the interrupt number by 4
o This gives the memory location containing the offset of the routine
o The segment number of the routine is in the next word

Example

• The keyboard interrupt routine is interrupt 9


• The offset address is stored in location 9x4 = 36 = 00024h
• The segment address is found in location 24h + 2 = 00026h
• BIOS initializes its interrupt vectors when the computer is turned on, and the DOS
interrupt vectors are initialized when DOS is loaded

Interrupt Routines

• When the CPU executes an INT instruction, it first saves the flags by pushing the
contents of the FLAGS register onto the stack
• Then it clears the control flags IF (interrupt flag) and TF (trap flag)
o The reason for this action is explained later
• Finally, it uses the interrupt number to get the interrupt vector from memory and
transfers control to the interrupt routine by loading CS:IP with the interrupt vector
o The 8086 transfers to a hardware interrupt routine or processor exception in
a similar fashion
• On completion, an interrupt routine executes an IRET (interrupt return) instruction
that restores the IP, CS, and FLAGS registers

The Control Flag TF

• When TF is set, the 8086 generates a processor exception (interrupt 1)


o This interrupt is used by debuggers to "single step" through a program
o To trace an instruction, the debugger first sets TF, and then transfers control
to the instruction to be traced
• After the instruction is executed, the processors generates an interrupt type 1
because TF is set
o The debugger uses its own interrupt 1 routine to gain control of the
processor

The Control Flag IF

• IF is used to control hardware interrupts


o When IF is set, hardware devices may interrupt the CPU
o External interrupts may be disabled (masked out) by clearing IF
o Actually, there is a hardware interrupt, called NMI (nonmaskable interrupt)
that cannot be masked out
• Both TF and IF are cleared by the processor before transferring to an interrupt
routine so that the routine will not be interrupted.
o Of course, an interrupt routine can change the flags to enable interrupts
during its execution

BIOS Interrupts

• Interrupt types 0 - 1Fh are BIOS interrupts whose service routines reside in ROM
segment F000h
• Interrupt 0 -- Divide Overflow: generated when a DIV or IDIV operation produces
an overflow
o The interrupt 0 routine displays the message "DIVIDE OVERFLOW" and
returns control to DOS
• Interrupt 1 -- Single Step: generated when the TF is set
• Interrupt 2 -- Nonmaskable Interrupt: cannot be masked out by clearing the IF
o The IBM PC uses this interrupt to signal memory and I/O parity errors that
indicate bad chips

• Interrupt 3 -- Breakpoint: used by debuggers to set up breakpoints


• Interrupt 4 -- Overflow: generated by the instruction INTO (interrupt if overflow)
when OF is set
o Programmers may write their own interrupt routine to handle unexpected
overflows
• Interrupt 5 -- Print Screen: The BIOS interrupt 5 routine sends the video screen
information to the printer
o An INT 5 instruction is generated by the keyboard interrupt routine (INT 9)
when the PrtScr key is pressed
• Interrupts 6&7 are reserved by Intel

• Interrupt 8 -- Timer: A timer circuit generates an interrupt once every 54.92


milliseconds
o The BIOS interrupt 8 routine services the timer circuit
 It users the timer signals to keep track of the time of day
• Interrupt 9 -- Keyboard: generated by the keyboard whenever a key is pressed or
released
o The service routine reads a scan code and stores it in the keyboard buffer
• Interrupt E -- Diskette Error: The BIOS interrupt routine Eh handles diskette errors

Interrupt Types 10h - 1Fh

• The interrupt routines 10h - 1Fh are software interrupts which can be called by
application programs to perform various I/O operations and status checking
• Interrupt 10h -- Video: The BIOS interrupt 10h routine is the video driver
o Details have been covered in a other units
• Interrupt 11h -- Equipment Check: returns the equipment configuration of the
particular PC
o The return code is placed in AX
o The table on the next slide shows how to interpret AX

Equipment Check

15-14 Number of printers installed


13 = 1 if internal modem installed
12 = 1 if game adapter installed
11-9 Number of serial ports installed
8 not used
7-6 Number of floppy drives (if bit 0=1)
00=1, 01=2KB, 10=3, 11=4
5-4 Initial video mode
00=not used, 01=40x25 color,
10=80x25 color, 11=80x25
monochrome
3-2 System board RAM size (original PC)
00=16KB, 01=32KB, 10=48KB, 11=64KB

1 = 1 if math coprocessor installed


0 = 1 if floppy drive installed
Interrupt Types 10h - 1Fh

• Interrupt 12h -- Memory Size: returns in AX the amount of conventional memory


o Conventional memory refers to memory circuits with address below 640K --
the unit for the return value is in kilobytes
o Example:
 Suppose a computer has 512KB of conventional memory. What will
be returned in AX if the instruction INT 12h is executed?
 512 = 200h, hence AX = 200h
• Interrupt 13h -- Disk I/O: The BIOS interrupt 13h routine is the disk driver; it
allows application programs to do disk I/O
o Most file operations are done through DOS INT 21h, functions 39h - 42h,
however; these utilize the BIOS INT 13h routine

• Interrupt 14h -- Communications: The communications driver that interacts with the
serial ports
• Interrupt 15h -- Cassette: Used by the original PC for the cassette interface
• Interrupt 16h -- Keyboard: the keyboard driver, discussed in a previous unit
• Interrupt 17h -- Printer I/O: the printer driver
o supports 3 functions, given by AH=0,1, or 2
 Function 0: writes character to the printer
 Function 1: initializes a printer port
 Function 2: gets printer status

• Interrupt 18h -- BASIC: transfers control to ROM BASIC


• Interrupt 19h -- Bootstrap: reboots the system
• Interrupt 1Ah -- Time of Day: allows a program to get and set the timer tick count
• Interrupt 1Bh -- Ctrl-Break: called by the INT 9 routine when Ctrl-Break is pressed
o The BIOS routine is a stub; it contains only an IRET instruction
o Users may write their own routines to handle the Ctrl-Break key
• Interrupt 1Ch -- Timer Tick: called by INT 8 each time the timer circuit interrupts --
as in INT 1Bh, the routine is a stub
• Interrupts 1Dh-1Fh: These interrupt vectors point to data instead of instructions
(video parameters, diskette parameters, and video graphics characters, respectively)

DOS Interrupts

• The interrupt types 20h-3Fh are serviced by DOS routines that provide high-level
service to hardware as well as system resources such as files and directories
• The most useful is INT 21h, which provides many functions for doing keyboard,
video, and file operations
DOS Interrupts 20h-27h

• Interrupt 20h -- Program Terminate: Terminates program, but it is better to use INT
21h, function 4Ch
• Interrupt 21h -- Function Request: Functions 0h-5Fh
o These functions may be classified as character I/O, file access, memory
management, disk access, networking, etc.
• Interrupt 22h-26h: These handle critical errors and direct disk access
• Interrupt 27h -- Terminate and Stay Resident: allows programs to stay in memory
after termination

A Time Display Program

• As an example of using interrupt routines, we now write a program that displays the
current time
o We will write three versions, each more complex
• The first version simply displays the current time in hours, minutes, and seconds
• The second version will show the time updated every second
• The third version will be a memory resident program that can display the time while
other programs are running

Clock at Power-up

• When the computer is powered up, the current time is usually supplied by a real-
time clock circuit that is battery powered
o If there is no real-time clock, DOS prompts the user to enter a time
• This time value is kept in memory and updated by a timer circuit using interrupt 8
• A program can call DOS interrupt 21h, function 2Ch, to access the time

INT 21h, Function 2Ch

• Time Of Day
• Input:
o AH = 2Ch
• Output:
o CH = hours (0 - 23)
o CL = minutes (0 - 59)
o DH = seconds (0 - 59)
o DL = 1/100 seconds (0 - 99)
• Returns the time: hours, minutes, seconds, and hundredths of seconds

How the Program Works

• Three steps
o obtains the current time (procedure GET_TIME)
o converts the hours, minutes, and seconds into ASCII digits (ignore the
fractions of seconds) (procedure CONVERT)
o display the ASCII digits
• A time buffer, TIME_BUF, is initialized with the message of 00:00:00
• The main procedure calls GET_TIME to store the current time in the time buffer

• The main procedure then calls INT 21h, function 9 to print out the string in the time
buffer
• GET_TIME calls INT 21h, function 2Ch to get the time, then calls CONVERT to
convert the time to ASCII characters
• CONVERT divides the input number in AL by 10; this will put the ten's digit in AL
and the one's digit in AH
• The second step is to convert the digits into ASCII
• The program displays the time and terminates

Program Listing (timedsp1.asm)


%TITLE "TIME_DISPLAY_VER_1"
;program that displays the current time
IDEAL
MODEL small
STACK 100h
DATASEG
TIME_BUF DB '00:00:00$' ;time buffer hr:min:sec
CODESEG
Start:
mov AX,@data
mov DS,AX ;initialize DS
;get and display time
lea BX,[TIME_BUF] ;BX points to TIME_BUF
call GET_TIME ;put current time in
TIME_BUF
lea DX,[TIME_BUF] ;DX points to TIME_BUF
mov AH,09h ;display time
int 21h
;exit
mov AH,4Ch ;return
int 21h ;to DOS
Procedure GET_TIME
PROC GET_TIME NEAR
;get time of day and store ASCII digits in time
buffer
;input: BX = address of time buffer
mov AH,2Ch ;gettime
int 21h ;CH = hr, CL = min, DH =
sec
;convert hours into ASCII and store
mov AL,CH ;hour
call CONVERT ;convert to ASCII
mov [BX],AX ;store
;convert minutes into ASCII and store
mov AL,CL ;minute
call CONVERT ;convert to ASCII
mov [BX+3],AX ;store
;convert seconds into ASCII and store
mov AL,DH ;second
call CONVERT ;convert to ASCII
mov [BX+6],AX ;store
ret

ENDP GET_TIME

Procedure CONVERT
PROC CONVERT
;converts byte number (0-59) into ASCII digits
;input: AL = number
;output: AX = ASCII digits, AL = high digit, AH =
low digit
mov AH,0 ;clear AH
mov DL,10 ;divide AX by 10
div DL ;AH has remainder, AL has
quotient
or AX,3030h ;convert to ASCII, AH has
low digit
ret ;AL has high digit
ENDP CONVERT
;

END Start

User Interrupt Procedures

• To make the time display program more interesting, let's write a second version that
displays the time and updates it every second
o One way to continuously update the time is to execute a loop that keeps
obtaining the time via INT 21h, function 2Ch and displaying it
o The problem here is to find a way to terminate the program
o Instead of pursing this approach, we will write a routine for interrupt 1Ch

INT 8 and INT 1Ch

• Interrupt 1Ch is generated by the INT 8 routine which is activated by a timer circuit
about 18.2 times per second
• We will write a new interrupt 1Ch routine so that when it is called, it will get the
time and display it
• Our program will have a main procedure that sets up the interrupt routine and when
a key is pressed, it will deactivate the interrupt routine and terminate

Set Interrupt Vector

• To set up an interrupt routine, we need to


o save the current interrupt vector
o place the vector of the user procedure in the interrupt vector table, and
o restore the previous vector before terminating the program
• We use INT 21h, function 35h to get the old vector and function 25h to set up the
new interrupt vector

INT 21h, Function 25h

• Set Interrupt Vector


Store interrupt vector into vector table
o Input:
 AH = 25h
 AL = Interrupt number
 DS:DX = interrupt vector
o Output:
 none

INT 21h, Function 35h

• Get Interrupt Vector


Obtain interrupt vector from vector table
o Input:
 AH = 35h
 AL = Interrupt number
o Output:
 ES:BX = interrupt vector

Procedure SETUP_INT

• The procedure SETUP_INT in program listing setupint.asm saves an old interrupt


vector and sets up a new vector
• It gets the interrupt number in AL, a buffer to save the old vector at DS:DI, and a
buffer containing the new interrupt vector at DS:SI
• By reversing the two buffers, SETUP_INT can also be used to restore the old vector

Cursor Control

• Each display of the current time by INT 21h, function 9, will advance the cursor
o If a new time is displayed, it appears at a different screen position
o So, to view the time updated at the same screen position we must restore the
cursor to its original position before we display the time
o This is achieved by first determining the current cursor position; then, after
each print string operation, we move the cursor back
• We use INT 10h, functions 2 and 3, to save the original cursor position and to move
the cursor to its original position after each print string operation

INT 10h, Function 2


Described in I/O module, repeated here for convenience

• Move Cursor
• Input:
o AH = 2
o DH = new cursor row (0-24)
o DL = new cursor column (0-79 for 80x25 mode)
o BH = page number
• Output: none

INT 10h, Function 3


Described in I/O module, repeated here for convenience

• Get Cursor Position and Size


• Input:
o AH = 3
o BH = page number
• Output:
o DH = cursor row
o DL = cursor column
o CH = cursor starting scan line
o CL = cursor ending scan line

Interrupt Procedure

• When an interrupt procedure is activated, it cannot assume that the DS register


contains the program's data segment address
• Thus, if it uses any variables it must first reset the DS register
• The DS register should be restored before ending the interrupt routine with IRET
DISPTIME2.ASM

• Program listing dsptime2.asm contains a main procedure and the interrupt


procedure TIME_INT
• the steps in the main procedure are
o save the current cursor position
o set up the interrupt vector for TIME_INT
o wait for a key input, and
o restore the old interrupt vector and terminate

Setting and Restoring the Interrupt Vector

• To set up the interrupt vector, we use the pseudo-ops OFFSET and SEG to obtain
the offset and segment of the TIME_INT routine
o The vector is then stored in the buffer NEW_VEC
• SETUP_INT is called to set up the vector for interrupt type 1Ch (timer tick)
• INT 16h, fcn 0 is used for key input
• SETUP_INT is again used for to restore the old interrupt vector
o this time SI points to the old vector and DI points to the vector for
TIME_INT

The TIME_INT Routine

• The steps in TIME_INT are


o set DS
o get new time
o display time
o restore cursor position, and
o restore DS

Outline of the Program

• The program operates like this:


o After setting up the cursor and interrupt vectors, the main procedure just
waits for a keystroke
o In the meantime, the interrupt routine (TIME_INT) keeps updating the time
whenever the timer circuit ticks
o After a key is hit, the old interrupt vector is restored and the program
terminates

Assembling and Linking

• The modules must be separately assembled and then linked with:

tlink timedsp2 setupint gettime


Memory Resident Program
• We will write the third version of DISPLAY_TIME as a TSR (terminate and stay
resident) program
• Normally, when a program terminates, the memory occupied by the program is used
by DOS to load other programs
• However, when a TSR program terminates, the memory occupied is not released
• Thus, a TSR program is also called a memory resident program

Terminating a TSR

• To return to DOS, a TSR program is terminated by using either INT 27h or INT
21h, function 31h
o Our program uses INT 27h
• We write our program as a .COM program because to use interrupt 27h, we need to
determine how many bytes are to remain memory resident
• The structure of a .COM program makes this easy, because there is only one
program segment
• .COM programs also are smaller, so they save space for TSRs

INT 27h

• Terminate and Stay Resident


• Input:
o DS:DX = address of byte beyond the part that is to remain resident
• Output:
o none

• Once terminated, a TSR program is not active


o It must be activated by some external activity, such as a certain key
combination or by the timer
• The advantage of a TRS program is that it may be activated while some other
program is running
o Our program will become active when the Ctrl and right shift keys are
pressed
• To keep the program small, it will not update the time

• The program has two parts:


o an initialization part that sets up the interrupt vector, and
o the interrupt routine itself
• The procedure INITIALIZE initializes the interrupt vector 9 (keyboard interrupt)
with the address of the interrupt procedure MAIN and then calls INT 27h to
terminate
• The address is passed to INT 27h is the beginning address of the INITIALIZE
procedure
o this is possible because the instructions are no longer needed
• The procedure INITIALIZE is shown in the program listing INITLZE.ASM
• There are a number of ways for the interrupt routine to detect a particular key
combination
o The simplest way is to detect the control and shift keys by checking the
keyboard flags
o When activated by a keystroke, the interrupt routine calls the old keyboard
interrupt routine to handle the key input
o To detect the control and shift keys, a program can examine the keyboard
flags at the BIOS data area 0000:0417h or use INT 16h, function 2

INT 16h, Function 2

• Get Keyboard Flags


• Input:
o AH = 2
• Output:
o AL = key flags

bit meaning

7=1 Insert on
6=1 Caps Lock on
5=1 Num Lock on
4=1 Scroll Lock on
3=1 Alt key down
2=1 Ctrl key down
1=1 Left shift key down
0=1 Right shift key down

• We will use the Ctrl and right shift key combination to activate and deactivate the
clock display
o When activated, the current time will be displayed on the upper right-hand
corner
o We must first save the screen data so that when the clock display is
deactivated the screen can be restored
• The procedure SET_CURSOR sets the cursor at row 0 and the column given in DL
• The procedure SAVE_SCREEN copies the screen data into a buffer called SS_BUF,
and the procedure RESTORE_SCREEN moves the data back to the screen buffer
• All three procedures are contained in SAVESCRN.ASM

• We are now ready to write the interrupt routine


• To determine whether to activate or deactivae the time display, we use the variable
ON_FLAG, which is set to 1 when the time is being displayed
• Procedure MAIN is the interrupt routine
• The steps in procedure MAIN are:
o save all registers used and set up the DS and ES registers
o call the old keyboard interrupt routine to handle the key input
o check to see if both Ctrl and right shift keys are down (if not, then exit)
o test ON_FLAG to determine status, and if ON_FLAG is 1 then restore
screen and exit
o save current cursor position and also the display screen info, and
o get time, display time, then exit

• In step 1, to set up the registers DS and ES, we use CS


o segment values cannot be used in a .COM program
• In step 2, we need to push the FLAGS register so that the procedure call simulates
an interrupt call
• In step 6, we use the BIOS interrupt 10h instead of DOS interrupt 21h, function 9 to
display the time because (from experience) INT 21h, function 9 tends to be
unreliable in a TSR program

• Because the program has been written as a .COM program, we need to rewrite the
file containing the GET_TIME procedure with full segment directives. The file
GETTIME2.ASM contains GET_TIME, CONVERT, and SETUP_INT
• The TLINK command should be

tlink /t timedsp3 savescrn gettime2 initlze

• Notice that initlze.obj is linked last so that the procedure INITIALIZE is


placed at the end of the program
• Writing TSR programs is tricky -- if there are other TSR programs on your system,
your program may not function properly
IBM PC/XT/AT & M24 BIOS SOFTWARE INTERRUPTS

Alarm Interrupt Vector - INT 4Ah


Cassette I/O - INT 15h
Diskette I/O - INT 13h
Fixed Disk I/O - INT 13h
Equipment Determination - INT 11h
IBM AT BIOS extensions - INT 15h
Keyboard I/P - INT 16h
Memory Size Determination - INT 12h
Parallel Printer O/P - INT 17h
RS232 Serial I/O - INT 14h
Time of Day - INT 1Ah
Timer Tick Interrupt Vector - INT 1Ch
Video Interrupt Service Routine - INT 10h

INT 10h - Video Interrupt Service Routine

(Technical References:
IBM AT - VIDEO 5-127 @ VIDEO_IO
IBM PC - A-43 @ F065h
IBM XT - System BIOS A-46 @ F065h
Olivetti M24 - D-148 & F065h)

AH = 00h - Set Mode & Clear Screen


01h - Set Cursor Value
02h - Set Cursor Position
03h - Read Cursor Position
04h - Read Light Pen Position
05h - Select Active Display Page
06h - Scroll Active Page Up
07h - Scroll Active Page Down
08h - Read Attribute & Character at Current Cursor
09h - Write Attribute & Character at Current Cursor
0Ah - Write Character at Current Cursor
0Bh - Set Overscan, Back & Foreground Colours
0Ch - Write Dot
0Dh - Read Dot
0Eh - Terminal Emulator for Active Page
0Fh - Read Current Video Status
10h-12h - Reserved
13h - Write String (IBM AT)
AH = 00h - Set Mode & Clear Screen

Input: AL = mode = 00h - text 40x 25 monochrome


= 01h - text 40x 25 colour
= 02h - text 80x 25 monochrome
= 03h - text 80x 25 colour
= 04h - graphics 320x200 colour
= 05h - graphics 320x200 monochrome
= 06h - graphics 640x200 monochrome
= 07h - text 80x 25 monochrome card
= 40h - graphics 640x400 monochrome (M24 only)
= 48h - graphics 640x400 monochrome tinytext (M24 only)

Output: AH = 00h
AL = palette colour

AH = 01h - Set Cursor Value

Input: CH bit#s 0-4 = starting line for cursor


CL bit#s 0-4 = ending line for cursor

Output: AH = 0Ah
AL = CL

Hardware will always cause blink. Setting bit#s 5-7 can cause errors.

AH = 02h - Set Cursor Position

Input: BH = page number (0-7 for text, 0 for graphics)


(DH,DL) = required (row,col) of cursor, ref (0,0) is upper left

Output: None

AH = 03h - Read Cursor Position

Input: BH = page number (0-7 for text, 0 for graphics)

Output: (DH,DL) = (row,col) of cursor, ref (0,0) at upper left


(CH,CL) = current cursor mode setting

AH = 04h - Read Light Pen Position

Output: AH = 0 - light pen not down/not triggered


AH = 1 - valid light pen values in the registers
(DH,DL) = (row,col) of character position
CH = rastor line (0-199/399)
BX = pixel column (0-319/639)

AH = 05h - Select Active Display Page

Input: AL = new page number (0-7 for modes 0-1, 0-3 for modes 2-3)

Output: None

AH = 06h - Scroll Active Page Up

Input: IF AL = 0, THEN clear entire window with attribute in BH


ELSE, AL = number of rows to 'scroll' up
= number of rows to clear at bottom of window
BH = attribute to be used on blank rows
(CH,CL) = (row,col) of upper left corner of window
(DH,DL) = (row,col) of lower right corner of window

Output: None

AH = 07h - Scroll Active Page Down

Input: IF AL = 0, THEN clear entire window with attribute in BH


ELSE, AL = number of rows to 'scroll' down
= number of rows to clear at top of window
BH = attribute to be used on blank rows
(CH,CL) = (row,col) of upper left corner of window
(DH,DL) = (row,col) of lower right corner of window

Output: None

AH = 08h - Read Attribute & Character at Current Cursor

Input: BH = display page

Output: AL = character read


AH = attribute of character

AH = 09h - Write Attribute & Character at Current Cursor

Input: AL = character to write


BH = display page
BL = attribute of character to write
CX = number of characters to write

Output: None

AH = 0Ah - Write Character at Current Cursor


Input: AL = character to write
BH = display page
CX = number of characters to write

Output: None

AH = 0Bh - Set Overscan, Back & Foreground Colours

Input: BH = palette colour ID to set (0-127)


BL = colour value to be used with that colour ID

Output: None

AH = 0Ch - Write Dot

Input: AL = colour value (if bit# 7 = 1, AL is XORed with current value)


CX = column number
DX = row number

Output: None

AH = 0Dh - Read Dot

Input: None

Output: AL = colour value


CX = column number
DX = row number

AH = 0Eh - Terminal Emulator for Active Page

Input: AL = character to write


BL = foreground colour (graphics mode)
BH = display page (alpha mode) (IBM PC)

Output: None

AH = 0Fh - Read Current Video Status

Input: None

Output: AH = number of character columns on screen


AL = display mode currently set
BH = current active display page

AH = 13h - Write String (IBM AT only


Input: AL = action byte
0 - use attribute in BL, cursor not moved
1 - use attribute in BL, cursor is moved
2 - string includes attribute, cursor not moved
3 - string includes attribute, cursor is moved

BH = page number
CX = length of character string to be written
DX = (DH,DL) = (row,col) of starting cursor position
ES:BP = pointer to string to be written:
either [char,char, ... ,char]
or [char,attrib,char,attrib, ... ,char,attrib]

Output: None

Note: IRET for IBM PX, XT and M24

INT 11h - Equipment Determination

(Technical References:
IBM AT - BIOS 5-143 @ EQUIPMENT
IBM PC - A-67 @ F84Dh
IBM XT - System BIOS A-71 @ F84Dh
Olivetti M24 - D-174 & F84Dh, D-88, & 2-106)

Input: None

Output: AX = equipment descriptor


bit#s 15,14 (C000h) = number of parallel ports attached
bit# 13 (2000h) not used
bit# 12 (1000h) = game i/o attached (IBM AT not used)
bit#s 11-9 (0E00h) = number of serial ports attached
bit# 8 (0100h) not used
bit#s 7,6 (00C0h) = # of diskette drives - 1 if bit# 0 = 1
bit#s 5,4 (0030h) = initial video mode
0 - unused
1 - 40x25 B&W using colour card
2 - 80x25 B&W using colour card
3 - 80x25 B&W using B&W card
bit#s 3,2 (000Ch) = Motherboard RAM size (IBM AT not used)
(0h=16k,4h=32k,8h=48k,Ch=64k)
bit# 1 (0002h) = math coprocessor (IBM AT only)
bit# 0 (0001h) = 1 indicates diskettes attached
INT 12h - Memory Size Determination

(Technical References:
IBM AT - BIOS 5-143 @ MEMORY_SIZE_DETERMINE
IBM PC - A-67 @ F841h
IBM XT - System BIOS A-71 @ F841h
Olivetti M24 - D-174 & F841h)

Input: None

Output: AX = number of contiguous 1k blocks of memory (-640)

INT 13h - Diskette I/O

(Technical References:
IBM AT - Diskette 5-89 @ DISKETTE_IO
IBM PC - A-32 @ EC59h
IBM XT - System BIOS A-34 @ EC59h
Olivetti M24 - D-132 & EC59h)

AH = 00h - Reset Diskette System


01h - Read Status of Last Operation to AL
02h - Read Sectors to Memory
03h - Write Sectors from Memory
04h - Verify the Desired Sectors
05h - Format the Specified Track
15h - Read DASD Type (AT only)
16h - Disk Change Line Status (AT only)
17h - Set DASD Type for Format (AT only)

Note: drive numbers are 0 & 1 for IBM AT & Olivetti M24, else 0-3.

AH = 00h - Reset Diskette System

Input: None (DL must be 0/1 on Olivetti M24)

Output: None

AH = 01h - Read Status of Last Operation to AL

Input: None (DL must be 0/1 on Olivetti M24)

Output: AL = status
80h - timeout
40h - bad seek
20h - disk controller failure
10h - bad CRC on diskette read
09h - attempt to DMA across 64k page boundary
08h - DMA overrun on i/o operation
06h - media removed (on dual attach card - AT)
04h - requested sector not found
03h - attempt to write on write protected disk
02h - address mark not found
01h - bad command
00h - operation successful

AH = 02h - Read Sectors to Memory

Input: AL = number of sectors to read (1-8/9,1-15)


CL = starting sector number (1-8/9,1-15)
CH = track number (0-39,0-79)
DL = drive number (0-1/3)
DH = head number (0/1)
ES:BX = address of buffer

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 03h - Write Sectors from Memory

Input: AL = number of sectors to write (1-8/9,1-15)


CL = starting sector number (1-8/9,1-15)
CH = track number (0-39,0-79)
DL = drive number (0-1/3)
DH = head number (0/1)
ES:BX = address of buffer

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 04h - Verify the Desired Sectors

Input: AL = number of sectors to verify (1-8/9,1-15)


CL = starting sector number (1-8/9,1-15)
CH = track number (0-39,0-79)
DL = drive number (0-1/3)
DH = head number (0/1)
ES:BX = address of buffer

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 05h - Format the Specified Track


Input: AL = number of sectors to format (1-8/9,1-15)
CH = track number (0-39,0-79)
DL = drive number (0-1/3)
DH = head number (0/1)
ES:BX = address of buffer (C,H,R,N,c,h,r,n...)

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

Note: In the IBM AT, function call 17 must be made to set the type

AH = 15h - Read DASD Type (AT only)

Input: DL = drive number (0-1)

Output: CF = 0/1 - operation successful/failure


AH = 00 - drive not present
01 - diskette, no change line available
02 - diskette, change line available
03 - fixed disk

AH = 16h - Disk Change Line Status (AT only)

Input: DL = drive number (0-1)

Output: CF = 0 & AH = 0 - disk change line not active


CF = 1 & AH = 6 - disk change line active

AH = 17h - Set DASD Type for Format (AT only)

Input: AL = 00 - not used


01 - diskette 320/360k in 320/360k drive
02 - diskette 320/360k in 1.2M drive
03 - diskette 1.2M in 1.2M drive
DL = drive number (0-1)

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

INT 13h - Fixed Disk I/O

(Technical References:
IBM AT - Disk 5-103 @ DISK_IO
IBM XT - Fixed Disk BIOS A-84 @ 0256h
Olivetti M24 - D-30 & D1A8h)
AH = 00h - Reset Disk
01h - Read Status of Last Operation to AL
02h - Read Sectors to Memory
03h - Write Sectors from Memory
04h - Verify the Desired Sectors
05h - Format the Specified Track
06h - Format the Specified Track and set Bad Sector Flags
07h - Format the Drive
08h - Return the Current Drive Parameters
09h - Initialize Drive Pair Characteristics
0Ah - Read Long
0Bh - Write Long
0Ch - Seek
0Dh - Alternate Disk Reset
0Eh - Read Sector Buffer
0Fh - Write Sector Buffer
10h - Test Drive Ready
11h - Recalibrate
12h - Controller RAM Diagnostic
13h - Drive Diagnostic
14h - Controller Internal Diagnostic
15h - Read DASD Type (AT only)
16h - Disk Change Line Status (AT only)
17h - Set DASD Type for Format (AT only)

Note: drive numbers are 80h-87h

AH = 00h - Reset Disk

Input: DL = drive number

Output: CF = 0/1 - operation successful/failure


AH = status

AH = 01h - Read Status of Last Operation to AL

Input: DL = drive number

Output: AL = status
FFh - sense fail
BBh - undefined error (XT)
80h - timeout
40h - bad seek
20h - disk controller failure
11h - data corrected by ECC (AL has burst length)
10h - bad ECC on diskette read
0Bh - bad track (M24)
09h - attempt to DMA across 64k page boundary
07h - drive parameter activity failed
05h - bad reset
04h - requested sector not found
02h - address mark not found
01h - bad command
00h - operation successful

AH = 02h - Read Sectors to Memory

Input: AL = number of sectors to read (1-80h)


CL = starting sector number (1-17)
CH = track number (0-1023, hi bits in bit# 7 & 6 of CL)
DL = drive number (80-87h)
DH = head number (0-7)
ES:BX = address of buffer

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 03h - Write Sectors from Memory

Input: AL = number of sectors to write (1-80h)


CL = starting sector number (1-17)
CH = track number (0-1023, hi bits in bit# 7 & 6 of CL)
DL = drive number (80-87h)
DH = head number (0-7)
ES:BX = address of buffer

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 04h - Verify the Desired Sectors

Input: AL = number of sectors to verify (1-80h)


CL = starting sector number (1-17)
CH = track number (0-1023, hi bits in bit# 7 & 6 of CL)
DL = drive number (80-87h)
DH = head number (0-7)
ES:BX = address of buffer

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 05h - Format the Specified Track


Input: AL = sector interleave (1-16)
CH = track number (0-1023, hi bits in bit# 7 & 6 of CL)
DL = drive number (80-87h)
DH = head number (0-7)

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

Note: The record buffer should be written before formatting

AH = 06h - Format the Specified Track, Setting Bad Sector Flags

Input: AL = sector interleave (1-16)


CH = track number (0-1023, hi bits in bit# 7 & 6 of CL)
DL = drive number (80-87h)
DH = head number (0-7)

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 07h - Format the Drive

Input: AL = sector interleave (1-16)


CH = starting track number (0-1023, hi bits in bit# 7 & 6 of CL)
DL = drive number (80-87h)
DH = head number (0-7)

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 08h - Return the Current Drive Parameters

Input: DL = drive number (80-87h)

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)
CL = Maximum value for sector number
CH = Maximum value for track number (hi bits in bit# 7 & 6 of CL)
DL = Number of drives attached (0-2)
DH = Maximum value for head number

AH = 09h - Initialize Drive Pair Characteristics

Input: DL = valid drive number

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)
Drive parameters at table pointed to by INT 41h

AH = 0Ah - Read Long Sectors to Memory

Input: AL = number of sectors to read (1-79h)


CL = starting sector number (1-17)
CH = track number (0-1023, hi bits in bit# 7 & 6 of CL)
DL = drive number (80-87h)
DH = head number (0-7)
ES:BX = address of buffer

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

Note: Read and Write long sectors are 512 bytes od data + 4 bytes ECC

AH = 0Bh - Write Long Sectors from Memory

Input: AL = number of sectors to write (1-79h)


CL = starting sector number (1-17)
CH = track number (0-1023, hi bits in bit# 7 & 6 of CL)
DL = drive number (80-87h)
DH = head number (0-7)
ES:BX = address of buffer

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 0Ch - Seek

Input: CH = track number (0-1023, hi bits in bit# 7 & 6 of CL)


DL = drive number (80-87h)
DH = head number (0-7)

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 0Dh - Alternate Disk Reset (without diskette reset)

Input: DL = drive number

Output: CF = 0/1 - operation successful/failure


AH = status

AH = 0Eh - Read Sector Buffer

Input: ES:BX = address of buffer


Output: CF = 0/1 - operation successful/failure
AH = status (see status call, AH=01h)

AH = 0Fh - Write Sector Buffer

Input: ES:BX = address of buffer

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 10h - Test Drive Ready

Input: DL = drive number

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 11h - Recalibrate

Input: DL = drive number

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 12h - Controller RAM Diagnostic

Input: None

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 13h - Drive Diagnostic

Input: DL = drive number

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 14h - Controller Internal Diagnostic

Input: None

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

AH = 15h - Read DASD Type (AT only)


Input: DL = drive number (0-1)

Output: CF = 0/1 - operation successful/failure


AH = 00 - drive not present
01 - diskette, no change line available
02 - diskette, change line available
03 - fixed disk

AH = 16h - Disk Change Line Status (AT only)

Input: DL = drive number (0-1)

Output: CF = 0 & AH = 0 - disk change line not active


CF = 1 & AH = 6 - disk change line active

AH = 17h - Set DASD Type for Format (AT only)

Input: AL = 00 - not used


01 - diskette 320/360k in 320/360k drive
02 - diskette 320/360k in 1.2M drive
03 - diskette 1.2M in 1.2M drive
DL = drive number (0-1)

Output: CF = 0/1 - operation successful/failure


AH = status (see status call, AH=01h)

INT 14h - RS232 Serial I/O

(Technical References:
IBM AT - RS232 5-125 @ RS232_IO
IBM PC - A-20 @ E739h
IBM XT - System BIOS A-21 @ E739h
Olivetti M24 - D-111 & E739h)

AH = 00h - Initialize the Communications Port


01h - Send the Byte in AL
02h - Receive a Byte from the Communications Port
03h - Return the Communcications Port status

AH = 00h - Initialize the Communications Port

Input: AL - parameters for initialization

--- baud rate ---- parity ---stops- word length -


bit# 7 6 5 4 3 2 1 0
000 - 110 X0 - NONE 0 - 1 10 - 7 bits
001 - 150 01 - ODD 1 - 2 11 - 8 bits
010 - 300 11 - EVEN
011 - 600
100 - 1200
101 - 2400
110 - 4800
111 - 9600

DX = RS232 port to access (0,1)

Output: AX - full port status (as for AH = 3)

Note: IBM allow 2 serial ports, Olivetti, 4

AH = 01h - Send the Byte in AL

Input: AL = byte to send


DX = port# (0,1)

Output: AH = line control status with bit# 7 set if unable to transmit

AH = 02h - Receive a Byte from the Communications Port

Input: DX = port# (0,1)

Output: AL = byte received


AH = current line status masked by 9Eh. i.e. error if <>0
bit# 7 = 1 - DSR not set

AH = 03h - Return the Communcications Port status

Input: DX = port# (0,1)

Output: AH = line control status


bit# 7 = time out (no DSR on Rx)
bit# 6 = Tx shift register empty
bit# 5 = Tx holding register empty
bit# 4 = bread detect
bit# 3 = framing error
bit# 2 = parity error
bit# 1 = overrun error
bit# 0 = data ready
AL = modem status
bit# 7 = receive line signal detect (DCD - pin 8)
bit# 6 = ring indicator (RI - pin 22)
bit# 5 = data set ready (DSR - pin 6)
bit# 4 = clear to send (CTS - pin 5)
bit# 3 = delta receive line signal detect
bit# 2 = trailing edge ring detector
bit# 1 = delta data set ready
bit# 0 = delta clear to send

INT 15h - Cassette i/o

(Technical References:
IBM AT - BIOS 1 5-147 @ CASSETTE_IO
IBM PC - A-68 @ F859h
IBM XT - System BIOS A-72 @ F859h
Olivetti M24 - D-175 & F859h)

AH = 00h - Turn Cassette Motor On (IBM PC only, not XT,AT or M24)


01h - Turn Cassette Motor Off (IBM PC only)
02h - Read 256 Byte Block(s) from Cassette (IBM PC only)
03h - Write 256 Byte Block(s) to Cassette (IBM PC only)

AH = 00h - Turn Cassette Motor On (IBM PC only)

Input: None

Output: CF = 0, AH = 0

Note: IBM XT, AT & M24: CF = 1, AH = 86h - bad command

AH = 01h - Turn Cassette Motor Off (IBM PC only)

Input: None

Output: CF = 0, AH = 0

Note: IBM XT, AT & M24: CF = 1, AH = 86h - bad command

AH = 02h - Read 256 Byte Block(s) from Cassette (IBM PC only)

Input: CX = number of bytes to read


ES:BX = pointer to data buffer

Output: DX = number of bytes read


ES:BX = pointer to last byte read + 1
CF = 0 & AH = 0 if no error occurred
CF = 1 & AH = 01h - CRC error was detected
AH = 02h - data transitions lost
AH = 03h - no data found

Note: IBM XT, AT & M24: CF = 1, AH = 86h - bad command

AH = 03h - Write 256 Byte Block(s) to Cassette (IBM PC only)

Input: CX = number of bytes to write


ES:BX = pointer to data buffer

Output: CX = 0
ES:BX = pointer to last byte written + 1
CF = 0 & AH = 0

Note: IBM XT, AT & M24: CF = 1, AH = 86h - bad command

INT 15h - IBM AT BIOS Extensions

(Technical References :
IBM AT - BIOS 1 5-147 @ CASSETTE_IO)

AH = 80h - Device Open


81h - Device Close
82h - Program Termination
83h - Event Wait
84h - Joystick Support
85h - System Request Key Pressed
86h - Wait
87h - Move Block To And From Extended Memory
88h - Extended Memory Size Determine
89h - Processor to Virtual Mode
90h - Device Busy Loop
91h - Interrupt Complete Flag Set

AH = 80h - Device Open

Input: BX = device ID
CX = process ID

Output: CF = 0 & AH = 0 - successful

Note: IBM AT: MOV AH,0 ! CLC ! RET 2 (BIOS 01/10/84)


IBM PC: CF = 1 & AH = 80h - undefined operation
IBM XT & M24: CF = 1 & AH = 86h - bad command

AH = 81h - Device Close


Input: BX = device ID
CX = process ID

Output: CF = 0 & AH = 0 - successful

Note: IBM AT: MOV AH,0 ! CLC ! RET 2 (BIOS 01/10/84)


IBM PC: CF = 1 & AH = 80h - undefined operation
IBM XT & M24: CF = 1 & AH = 86h - bad command

AH = 82h - Program Termination

Input: BX = device ID

Output: CF = 0 & AH = 0 - successful

Note: IBM AT: MOV AH,0 ! CLC ! RET 2 (BIOS 01/10/84)


IBM PC: CF = 1 & AH = 80h - undefined operation
IBM XT & M24: CF = 1 & AH = 86h - bad command

AH = 83h - Event Wait

Input: AL = 0 - set interval


(CX,DX) = number of microseconds to delay (CX = MSW)
(ES:BX) = pointer to byte that will have bit# 7 set when time interval has
expired
AL = 1 - cancel (BIOS 01/10/84 code assumes AL = 0!)

Output: CF = 0 - interval timer set


CF = 1 - interval timer already in use

Note: IBM PC: CF = 1 & AH = 80h - undefined operation


IBM XT & M24: CF = 1 & AH = 86h - bad command

AH = 84h - Joystick Support

Input: DX = 0 - read the current switch settings


1 - read the resistive inputs

Output: CF = 0 - operation complete


AL has switch settings in bit#s 7-4 or
AX = A(x) value
BX = A(y) value
CX = B(x) value
DX = B(y) value
CF = 1 - no adaptor card or invalid call

Note: IBM PC: CF = 1 & AH = 80h - undefined operation


IBM XT & M24: CF = 1 & AH = 86h - bad command

AH = 85h - System Request Key Pressed

Input: AL = 0 - make of key


1 - break of key

Output: CF = 0 & AH = 0 - successful

Note: IBM AT: MOV AH,0 ! CLC ! RET 2 (BIOS 01/10/84)


IBM PC: CF = 1 & AH = 80h - undefined operation
IBM XT & M24: CF = 1 & AH = 86h - bad command

AH = 86h - Wait

Input: (CX,DX) = number of microseconds to delay (CX = MSW)

Output: CF = 0 - have done delay


CF = 1 - interval timer already in use

Note: IBM PC: CF = 1 & AH = 80h - undefined operation


IBM XT & M24: CF = 1 & AH = 86h - bad command

AH = 87h - Move Block To And From Extended Memory

Input: CX = number of words to move (max count = 8000h, 32k words)


ES:SI = location of Global Descriptor Table
DESCRIPT STRUC
SEG_LIMIT DW ? ; segment limit (1-64k bytes)
BASE_LO DW ? ; 24 bit absolute address of
BASE_HI DB ? ; segment
ACCESS DB ? ; access rights byte
DW ? ; reserved
DESCRIPT ENDS
GDT STRUC
DUMMY DQ ? ; dummy descript initialized to zero
CGDT_LOC DQ ? ; location of calling routine (all 0's)
SOURCE DQ ? ; source descriptor (set by user)
TARGET DQ ? ; target descriptor (set by user)
BIOS_CS DQ ? ; BIOS code descriptor (all 0's)
TEMP_SS DQ ? ; stack descriptor (all 0's)
GDT ENDS

Output: CF = 0 & ZF = 1 & AH = 0 - successful


CF = 1 & ZF = 0 & AH = 1 - RAM parity error
CF = 1 & ZF = 0 & AH = 2 - exception interrupt error
CF = 1 & ZF = 0 & AH = 3 - gate address line 20 failed
Note: IBM PC: CF = 1 & AH = 80h - undefined operation
IBM XT & M24: CF = 1 & AH = 86h - bad command

AH = 88h - Extended Memory Size Determine

Input: None

Output: AX = number of contiguous 1k blocks starting at 1024k

Note: IBM PC: CF = 1 & AH = 80h - undefined operation


IBM XT & M24: CF = 1 & AH = 86h - bad command

AH = 89h - Processor to Virtual Mode

Input: ES:SI = location of Global Descriptor Table


DESCRIPT STRUC
SEG_LIMIT DW ? ; segment limit (1-64k bytes)
BASE_LO DW ? ; 24 bit absolute address of
BASE_HI DB ? ; segment
ACCESS DB ? ; access rights byte
DW ? ; reserved
DESCRIPT ENDS
GDT STRUC
DUMMY DQ ? ; dummy descript initialized to zero
GDTPTR DQ ? ; location of calling routine
IDTPTR DQ ? ; IDT descriptor
USER_DS DQ ? ; data segment descriptor
USER_ES DQ ? ; extra segment descriptor
USER_SS DQ ? ; stack segment descriptor
USER_CS DQ ? ; code segment descriptor
BIOS_CS DQ ? ; BIOS code descriptor (all 0's)
GDT ENDS

Output: AH = 0 - successful
CF = 1 & ZF = 0 & AH = FFh - gate address line 20 failed

Note: IBM PC: CF = 1 & AH = 80h - undefined operation


IBM XT & M24: CF = 1 & AH = 86h - bad command

AH = 90h - Device Busy Loop

Input: AL = type code


00-7Fh = serially reusable devices; operating system must serialize access
80-BFh = reentrant devices; ES:BX is used to distinguish calls (multiple i/o
calls are allowed simultaneously)
C0-FFh = wait only calls; these are timeout dependent. times are function
number dependent
e.g. 00h = disk (timeout)
01h = diskette (timeout)
02h = keyboard (no timeout)
80h = network (no timeout) ES:BX --> NCB
FDh = diskette motor start (timeout)
FEh = printer (timeout)

Output: CF = 0 & AH = 0 - successful

Note: IBM AT: MOV AX,0 ! CLC ! RET 2 (BIOS 01/10/84)


IBM PC: CF = 1 & AH = 80h - undefined operation
IBM XT & M24: CF = 1 & AH = 86h - bad command

AH = 91h - Interrupt Complete Flag Set

Input: AL = type code as described for AH = 90h above

Output: Flags restored, AX = 0

Note: IBM AT: MOV AX,0 ! IRET (BIOS 01/10/84)


IBM PC: CF = 1 & AH = 80h - undefined operation
IBM XT & M24: CF = 1 & AH = 86h - bad command

INT 16h - Keyboard I/P

(Technical References:
IBM AT - KEYBOARD 5-115 @ KEYBOARD_IO
IBM PC - A-23 @ E82Eh
IBM XT - System BIOS A-24 @ E82Eh
Olivetti M24 - D-114 & E82Eh)

AH = 00h - Read the next key struck from the keyboard


01h - Return 'key struck' status of keyboard
02h - Return current shift status of keyboard

AH = 00 - Read the next key struck into AX

Input: None

Output: AH = scan code


AL = character code

AH = 01h - Return 'key struck' status of keyboard


Input: None

Output: ZF = 1 - no code available


ZF = 0 - code is available and is returned in AX
AX = scan code & character code as above. The keyboard
buffer is not altered

AH = 02h - Return current shift status of keyboard

Input: None

Output: AL = shift status


bit# 7 - insert state active
bit# 6 - Caps Lock toggled
bit# 5 - Num Lock toggled
bit# 4 - Scroll Lock toggled
bit# 3 - Alt shift key depressed
bit# 2 - Ctrl shift key depressed
bit# 1 - left Shift key depressed
bit# 0 - right Shift key depressed

INT 17h - Parallel Printer O/P

(Technical References:
IBM AT - PRINTER 5-123 @ PRINTER_IO
IBM PC - A-42 @ EFD2h
IBM XT - System BIOS A-44 @ EFD2h
Olivetti M24 - D-144 & EFD2h)

AH = 00h - Print the character in AL


01h - Initialize the printer port
02h - Read the printer status into AH

AH = 00 - Print the character in AL

Input: AL = character to send


DX = printer to use (0-2)

Output: AH = 1 if character could not be printed


AH <> 1 = current status

Note: The IBM allow 3 printer ports, Olivetti, 4

AH = 01h - Initialize the printer port

Input: DX = printer # (0-2)


Output: AH = printer status

AH = 02h - Read the printer status into AH

Input: DX = printer # (0-2)

Output: AH = printer status byte


bit# 0 - time out
bit#s 1 & 2 - unused
bit# 3 - i/o error (NOT pin 15)
bit# 4 - selected (pin 13)
bit# 5 - out of paper (pin 12)
bit# 6 - acknowledge (NOT pin 10)
bit# 7 - not busy (NOT pin 11)

Note: 'Good' statuses are 90h & 10h if a printer is connected,


30h if printer is disconnected.

INT 1Ah - Time of Day

(Technical References:
IBM AT - BIOS 2 5-159 @ TIME_OF_DAY
IBM PC - A-77 @ FE6Eh
IBM XT - System BIOS A-79 @ FE6Eh
Olivetti M24 - D-188 & FE6Eh)

AH = 00h - Read the Current Clock Setting


01h - Set the Current Clock
02h - Read the Real Time Clock (IBM AT only)
03h - Set the Real Time Clock (IBM AT only)
04h - Read the Date (IBM AT only)
05h - Set the Date (IBM AT only)
06h - Set the Alarm (IBM AT only)
07h - Reset the Alarm (IBM AT only)
FEh - Read Clock Calendar Device (M24 only)
FFh - Write Clock Calendar Device (M24 only)

AH = 00 - Read the Current Clock Setting

Input: None

Output: AL <> 0 if timer has passed 24 hours since last read


CX = high portion of count
DX = low portion of count
Note: Counts occur at 1193180/65536 counts/sec (18.2 per sec)
INT 1Ch is accessed at each count

AH = 01h - Set the Current Clock

Input: CX = high portion of count


DX = low portion of count

Output: None

AH = 02h - Read the Real Time Clock (IBM AT only)

Input: None

Output: CF = 0, CH = hours in BCD


CL = minutes in BCD
DH = seconds in BCD
CF = 1 - clock not operating

Note: NOP for IBM PC, XT & M24

AH = 03h - Set the Real Time Clock (IBM AT only)

Input: CH = hours in BCD


CL = minutes in BCD
DH = seconds in BCD
DL = 1 if daylight savings time option, else 0

Output: None

Note: NOP for IBM PC, XT & M24

AH = 04h - Read the Date (IBM AT only)

Input: None

Output: CF = 0, CH = 19 or 20, century in BCD


CL = year in BCD
DH = month in BCD
DL = day in BCD
CF = 1 - clock not operating

Note: NOP for IBM PC, XT & M24

AH = 05h - Set the Date (IBM AT only)

Input: CH = century in BCD (19 or 20)


CL = year in BCD
DH = month in BCD
DL = day in BCD

Output: None

Note: NOP for IBM PC, XT & M24

AH = 06h - Set the Alarm (IBM AT only)

Input: CH = hours in BCD


CL = minutes in BCD
DH = seconds in BCD
Set alarm vector in INT 4Ah

Output: CF = 0 - alarm set


CF = 1 - clock not operating or alarm already set

Note: NOP for IBM PC, XT & M24

AH = 07h - Reset the Alarm (IBM AT only)

Input: None

Output: None

Note: NOP for IBM PC, XT & M24

AH = FEh - Read Clock Calendar Device (M24 only)

Input: None

Output: BX = day from 1-1 of leap year up to 12-31 of leap year+7


CH = hour
CL = minutes
DH = seconds
DL = hundredths of seconds

Note: Resets Alarm in IBM AT


NOP for IBM PC, XT

AH = FFh - Write Clock Calendar Device (M24 only)

Input: BX = day from 1-1 of leap year up to 12-31 of leap year+7


CH = hour (0-23)
CL = minutes (0-59)

Output: AH = -1 - date time error


= 0 - date time OK

Note: Resets Alarm in IBM AT


NOP for IBM PC, XT

INT 1Ch - Timer Tick Interrupt

(Technical References:
IBM AT - BIOS 2 5-162
IBM PC - A-78 @ FEE9h
IBM XT - System BIOS A-79 @ FEE3h
Olivetti M24 - D-190 & FEE2h)

This interrupt is called every time the time of day clock 'ticks' (approximately 18.2 Hz). The
8259 PIC is not sent an End of Interrupt until the IRET from this routine.

Care should be taken to save the current INT 1Ch vector and chain to it after the service
routine is finished.

INT 4Ah - Alarm Interrupt (IBM AT)

(Technical References:
IBM AT - BIOS 2 5-159)

This interrupt is called when the Real Time Clock alarm is set off. The alarm should be
reset before the IRET.