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 0h-1Fh 20h-3Fh 40h-7Fh 80h-F0h F1h-FFh
Description BIOS Interrupts DOS Interrupts reserved ROM BASIC 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)
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 o
•
•
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 13 = 1 12 = 1 11-9 8 7-6 5-4
Number of printers installed if internal modem installed if game adapter installed Number of serial ports installed not used Number of floppy drives (if bit 0=1) 00=1, 01=2KB, 10=3, 11=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 0 = 1
if math coprocessor installed 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 realtime 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)
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 o
• • • • • • •
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 6=1 5=1 4=1 3=1 2=1 1=1 0=1
Insert on Caps Lock on Num Lock on Scroll Lock on Alt key down Ctrl key down Left shift key down 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 001 - 150 010 - 300 011 - 600 100 - 1200 101 - 2400 110 - 4800 111 - 9600
X0 - NONE 0 - 1 10 - 7 bits 01 - ODD 1 - 2 11 - 8 bits 11 - EVEN
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.