BIOS and DOS Interrupts
BIOS and DOS Interrupts
• These notes roughly correspond to text chapter 10, although the approach is
considerably different
Overview
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
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
Software Interrupt
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
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
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
• 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
• 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
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
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
• 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
• 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
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
• 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
• 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
• 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
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
• 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
• 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
Procedure SETUP_INT
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
• 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
Interrupt Procedure
• 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
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
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
• 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
(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)
Output: AH = 00h
AL = palette colour
Output: AH = 0Ah
AL = CL
Hardware will always cause blink. Setting bit#s 5-7 can cause errors.
Output: None
Input: AL = new page number (0-7 for modes 0-1, 0-3 for modes 2-3)
Output: None
Output: None
Output: None
Output: None
Output: None
Output: None
Output: None
Input: None
Output: None
Input: None
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
(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
(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
(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)
Note: drive numbers are 0 & 1 for IBM AT & Olivetti M24, else 0-3.
Output: None
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
Note: In the IBM AT, function call 17 must be made to set the type
(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)
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
Note: Read and Write long sectors are 512 bytes od data + 4 bytes ECC
AH = 0Ch - Seek
AH = 11h - Recalibrate
Input: None
Input: None
(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)
(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)
Input: None
Output: CF = 0, AH = 0
Input: None
Output: CF = 0, AH = 0
Output: CX = 0
ES:BX = pointer to last byte written + 1
CF = 0 & AH = 0
(Technical References :
IBM AT - BIOS 1 5-147 @ CASSETTE_IO)
Input: BX = device ID
CX = process ID
Input: BX = device ID
AH = 86h - Wait
Input: None
Output: AH = 0 - successful
CF = 1 & ZF = 0 & AH = FFh - gate address line 20 failed
(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)
Input: None
Input: None
(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)
(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)
Input: None
Output: None
Input: None
Output: None
Input: None
Output: None
Input: None
Output: None
Input: None
(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.
(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.