Recent from talks
Nothing was collected or created yet.
BIOS interrupt call
View on WikipediaThis article has multiple issues. Please help improve it or discuss these issues on the talk page. (Learn how and when to remove these messages)
|
BIOS implementations provide interrupts that can be invoked by operating systems and application programs to use the facilities of the firmware on IBM PC compatible[a] computers. Traditionally, BIOS calls are mainly used by DOS programs and some other software such as boot loaders (including, mostly historically, relatively simple application software that boots directly and runs without an operating system—especially game software). BIOS runs in the real address mode (Real Mode) of the x86 CPU, so programs that call BIOS either must also run in real mode or must switch from protected mode to real mode before calling BIOS and then switching back again. For this reason, modern operating systems that use the CPU in Protected mode or Long mode generally do not use the BIOS interrupt calls to support system functions, although they use the BIOS interrupt calls to probe and initialize hardware during booting.[1] Real mode has the 1MB memory limitation, modern boot loaders (e.g. GRUB2, Windows Boot Manager) use the unreal mode or protected mode (and execute the BIOS interrupt calls in the Virtual 8086 mode, but only for OS booting) to access up to 4GB memory.[2]
In all computers, software instructions control the physical hardware (screen, disk, keyboard, etc.) from the moment the power is switched on. In a PC, the BIOS, pre-loaded in ROM on the motherboard, takes control immediately after the CPU is reset, including during power-up, when a hardware reset button is pressed, or when a critical software failure (a triple fault) causes the mainboard circuitry to automatically trigger a hardware reset. The BIOS tests the hardware and initializes its state; finds, loads, and runs the boot program (usually, an OS boot loader, and historical ROM BASIC); and provides basic hardware control to the software running on the machine, which is usually an operating system (with application programs) but may be a directly booting single software application.
For IBM's part, they provided all the information needed to use their BIOS fully or to directly utilize the hardware and avoid BIOS completely, when programming the early IBM PC models (prior to the PS/2). From the beginning, programmers had the choice of using BIOS or not, on a per-hardware-peripheral basis. IBM did strongly encourage the authorship of "well-behaved" programs that accessed hardware only through BIOS INT calls (and DOS service calls), to support compatibility of software with current and future PC models having dissimilar peripheral hardware, but IBM understood that for some software developers and hardware customers, a capability for user software to directly control the hardware was a requirement. In part, this was because a significant subset of all the hardware features and functions was not exposed by the BIOS services. For two examples (among many), the MDA and CGA adapters are capable of hardware scrolling, and the PC serial adapter is capable of interrupt-driven data transfer, but the IBM BIOS supports neither of these useful technical features.
Today, the BIOS in a new PC still supports most, if not all, of the BIOS interrupt function calls defined by IBM for the IBM AT (introduced in 1984), along with many more newer ones, plus extensions to some of the originals (e.g. expanded parameter ranges) promulgated by various other organizations and collaborative industry groups. This, combined with a similar degree of hardware compatibility, means that most programs written for an IBM AT can still run correctly on a new PC today, assuming that the faster speed of execution is acceptable (which it typically is for all but games that use CPU-based timing). Despite the considerable limitations of the services accessed through the BIOS interrupts, they have proven extremely useful and durable to technological change.
Purpose of BIOS calls
[edit]BIOS interrupt calls perform hardware control or I/O functions requested by a program, return system information to the program, or do both. A key element of the purpose of BIOS calls is "black box" abstraction - the BIOS calls perform generally defined functions, and the specific details of how those functions are executed on the particular hardware of the system are encapsulated in the BIOS and hidden from the program. So, for example, a program that wants to read from a hard disk does not need to know whether the hard disk is an ATA, SCSI, or SATA drive (or in earlier days, an ESDI drive, or an MFM or RLL drive with perhaps a Seagate ST-506 controller, perhaps one of the several Western Digital controller types, or with a different proprietary controller of another brand). The program only needs to identify the BIOS-defined number of the drive it wishes to access and the address of the sector it needs to read or write, and the BIOS will take care of translating this general request into the specific sequence of elementary operations required to complete the task through the particular disk controller hardware that is connected to that drive. The program is freed from needing to know how to control at a low level every type of hard disk (or display adapter, or port interface, or real-time clock peripheral) that it may need to access. This both makes programming operating systems and applications easier and makes the programs smaller, reducing the duplication of program code, as the functionality that is included in the BIOS does not need to be included in every program that needs it; relatively short calls to the BIOS are included in the programs instead. (In operating systems where the BIOS is not used, service calls provided by the operating system itself generally fulfill the same function and purpose.)
The BIOS also frees computer hardware designers (to the extent that programs are written to use the BIOS exclusively) from being constrained to maintain exact hardware compatibility with old systems when designing new systems, in order to maintain compatibility with existing software. For example, the keyboard hardware on the IBM PCjr works very differently than the keyboard hardware on earlier IBM PC models, but to programs that use the keyboard only through the BIOS, this difference is nearly invisible. (As a good example of the other side of this issue, a significant share of the PC programs in use at the time the PCjr was introduced did not use the keyboard through BIOS exclusively, so IBM also included hardware features in the PCjr to emulate the way the original IBM PC and IBM PC XT keyboard hardware works. The hardware emulation is not exact, so not all programs that try to use the keyboard hardware directly will work correctly on the PCjr, but all programs that use only the BIOS keyboard services will.)
In addition to giving access to hardware facilities, BIOS provides added facilities that are implemented in the BIOS software. For example, the BIOS maintains separate cursor positions for up to eight text display pages and provides for TTY-like output with automatic line wrap and interpretation of basic control characters such as carriage return and line feed, whereas the CGA-compatible text display hardware has only one global display cursor and cannot automatically advance the cursor, use the cursor position to address the display memory (so as to determine which character cell will be changed or examined), or interpret control characters. For another example, the BIOS keyboard interface interprets many keystrokes and key combinations to keep track of the various shift states (left and right Shift, Ctrl, and Alt), to call the print-screen service when Shift+PrtScrn is pressed, to reboot the system when Ctrl+Alt+Del is pressed, to keep track of the lock states (Caps Lock, Num Lock, and Scroll Lock) and, in AT-class machines, control the corresponding lock-state indicator lights on the keyboard, and to perform other similar interpretive and management functions for the keyboard. In contrast, the ordinary capabilities of the standard PC and PC-AT keyboard hardware are limited to reporting to the system each primitive event of an individual key being pressed or released (i.e. making a transition from the "released" state to the "depressed" state or vice versa), performing a commanded reset and self-test of the keyboard unit, and, for AT-class keyboards, executing a command from the host system to set the absolute states of the lock-state indicators (LEDs).
Calling BIOS: BIOS software interrupts
[edit]Operating systems and other software communicate with the BIOS software, in order to control the installed hardware, via software interrupts. A software interrupt is a specific variety of the general concept of an interrupt. An interrupt is a mechanism by which the CPU can be directed to stop executing the main-line program and immediately execute a special program, called an Interrupt Service Routine (ISR), instead. Once the ISR finishes, the CPU continues with the main program. On x86 CPUs, when an interrupt occurs, the ISR to call is found by looking it up in a table of ISR starting-point addresses (called "interrupt vectors") in memory: the Interrupt vector table (IVT). An interrupt is invoked by its type number, from 0 to 255, and the type number is used as an index into the Interrupt Vector Table, and at that index in the table is found the address of the ISR that will be run in response to the interrupt. A software interrupt is simply an interrupt that is triggered by a software command; therefore, software interrupts function like subroutines, with the main difference that the program that makes a software interrupt call does not need to know the address of the ISR, only its interrupt number. This has advantages for modularity, compatibility, and flexibility in system configuration.
BIOS interrupt calls can be thought of as a mechanism for passing messages between BIOS and BIOS client software such as an operating system. The messages request data or action from BIOS and return the requested data, status information, and/or the product of the requested action to the caller. The messages are broken into categories, each with its own interrupt number, and most categories contain sub-categories, called "functions" and identified by "function numbers". A BIOS client passes most information to BIOS in CPU registers, and receives most information back the same way, but data too large to fit in registers, such as tables of control parameters or disk sector data for disk transfers, is passed by allocating a buffer (i.e. some space) in memory and passing the address of the buffer in registers. (Sometimes multiple addresses of data items in memory may be passed in a data structure in memory, with the address of that structure passed to BIOS in registers.) The interrupt number is specified as the parameter of the software interrupt instruction (in Intel assembly language, an "INT" instruction), and the function number is specified in the AH register; that is, the caller sets the AH register to the number of the desired function. In general, the BIOS services corresponding to each interrupt number operate independently of each other, but the functions within one interrupt service are handled by the same BIOS program and are not independent. (This last point is relevant to reentrancy.)
The BIOS software usually returns to the caller with an error code if not successful, or with a status code and/or requested data if successful. The data itself can be as small as one bit or as large as 65,536 bytes of whole raw disk sectors (the maximum that will fit into one real-mode memory segment). BIOS has been expanded and enhanced over the years many times by many different corporate entities, and unfortunately the result of this evolution is that not all the BIOS functions that can be called use consistent conventions for formatting and communicating data or for reporting results. Some BIOS functions report detailed status information, while others may not even report success or failure but just return silently, leaving the caller to assume success (or to test the outcome some other way). Sometimes it can also be difficult to determine whether or not a certain BIOS function call is supported by the BIOS on a certain computer, or what the limits of a call's parameters are on that computer. (For some invalid function numbers, or valid function numbers with invalid values of key parameters—particularly with an early IBM BIOS version—the BIOS may do nothing and return with no error code; then it is the [inconvenient but inevitable] responsibility of the caller either to avoid this case by not making such calls, or to positively test for an expected effect of the call rather than assuming that the call was effective. Because BIOS has evolved extensively in many steps over its history, a function that is valid in one BIOS version from some certain vendor may not be valid in an earlier or divergent BIOS version from the same vendor or in a BIOS version—of any relative age—from a different vendor.)
Because BIOS interrupt calls use CPU register-based parameter passing, the calls are oriented to being made from assembly language and cannot be directly made from most high-level languages (HLLs). However, a high level language may provide a library of wrapper routines which translate parameters from the form (usually stack-based) used by the high-level language to the register-based form required by BIOS, then back to the HLL calling convention after the BIOS returns. In some variants of C, BIOS calls can be made using inline assembly language within a C module. (Support for inline assembly language is not part of the ANSI C standard but is a language extension; therefore, C modules that use inline assembly language are less portable than pure ANSI standard C modules.)
Invoking an interrupt
[edit]Invoking an interrupt can be done using the INT x86 assembly language instruction. For example, to print a character to the screen using BIOS interrupt 0x10, the following x86 assembly language instructions could be executed:
mov ah, 0x0e ; function number = 0Eh : Display Character
mov al, '!' ; AL = code of character to display
int 0x10 ; call INT 10h, BIOS video service
Interrupt table
[edit]A list of common BIOS interrupt classes can be found below. Some BIOSes (particularly old ones) do not implement all of these interrupt classes.
The BIOS also uses some interrupts to relay hardware event interrupts to programs which choose to receive them or to route messages for its own use.
| Interrupt vector | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
05h
|
Executed when Shift-Print screen is pressed, as well as when the BOUND instruction detects a bound failure.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
08h
|
This is the real time clock interrupt. It fires 18.2 times/second. The BIOS increments the time-of-day counter during this interrupt. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
09h
|
This is the Keyboard interrupt. This is generally triggered when a key on a keyboard is pressed. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
10h
|
Video Services
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
11h
|
Returns equipment list | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
12h
|
Return conventional memory size | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
13h
|
Low Level Disk Services
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
14h
|
Serial port services
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
15h
|
Miscellaneous system services
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
16h
|
Keyboard services
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
17h
|
Printer services
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
18h
|
Execute Cassette BASIC: On IBM machines up to the early PS/2 line, this interrupt would start the ROM Cassette BASIC. Clones did not have this feature and different machines/BIOSes would perform a variety of different actions if INT 18h was executed, most commonly an error message stating that no bootable disk was present. Modern machines would attempt to boot from a network through this interrupt. On modern machines this interrupt will be treated by the BIOS as a signal from the bootloader that it failed to complete its task. The BIOS can then take appropriate next steps.[3] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
19h
|
After POST this interrupt is used by the BIOS to load the operating system. A program can call this interrupt to reboot the computer (but must ensure that hardware interrupts or DMA operations will not cause the system to hang or crash during either the reinitialization of the system by BIOS or the boot process). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1Ah
|
Real-time clock (RTC) Services
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1Ah
|
PCI Services - implemented by BIOSes supporting PCI 2.0 or later
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1Bh
|
Ctrl-Break handler - called by INT 09 when Ctrl-Break has been pressed
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1Ch
|
Timer tick handler - called by INT 08
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1Dh
|
Not to be called; simply a pointer to the VPT (Video Parameter Table), which contains data on video modes | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1Eh
|
Not to be called; simply a pointer to the DPT (Diskette Parameter Table), containing a variety of information concerning the diskette drives | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1Fh
|
Not to be called; simply a pointer to the VGCT (Video Graphics Character Table), which contains the data for ASCII characters 80h to FFh
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
41h
|
Address pointer: FDPT = Fixed Disk Parameter Table (1st hard drive) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
46h
|
Address pointer: FDPT = Fixed Disk Parameter Table (2nd hard drive) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4Ah
|
Called by real-time clock for alarm |
INT 18h: execute BASIC
[edit]INT 18h traditionally jumped to an implementation of Cassette BASIC (provided by Microsoft) stored in Option ROMs. This call would typically be invoked if the BIOS was unable to identify any bootable disk volumes on startup.
At the time the original IBM PC (IBM machine type 5150) was released in 1981, the BASIC in ROM was a key feature. Contemporary popular personal computers such as the Commodore 64 and the Apple II line also had Microsoft Cassette BASIC in ROM (though Commodore renamed their licensed version Commodore BASIC), so in a substantial portion of its intended market, the IBM PC needed BASIC to compete. As on those other systems, the IBM PC's ROM BASIC served as a primitive diskless operating system, allowing the user to load, save, and run programs, as well as to write and refine them. (The original IBM PC was also the only PC model from IBM that, like its aforementioned two competitors, included cassette interface hardware. A base model IBM PC had only 16 KiB of RAM and no disk drives of any kind, so the cassette interface and BASIC in ROM were essential to make the base model usable. An IBM PC with less than 32 KiB of RAM is incapable of booting from disk. Of the five 8 KiB ROM chips in an original IBM PC, totaling 40 KiB, four contain BASIC and only one contains the BIOS; when only 16 KiB of RAM are installed, the ROM BASIC accounts for 4/7ths of the total system memory.)
As time went on and BASIC was no longer shipped on all PCs, this interrupt would simply display an error message indicating that no bootable volume was found (such as "No ROM BASIC", or more explanatory messages in later BIOS versions); in other BIOS versions it would prompt the user to insert a bootable volume and press a key, and then after the user pressed a key it would loop back to the bootstrap loader (INT 19h) to try booting again.
Digital's Rainbow 100B used INT 18h to call its BIOS, which was incompatible with the IBM BIOS. Turbo Pascal, Turbo C and Turbo C++ repurposed INT 18 for memory allocation and paging. Other programs also reused this vector for their own purposes.
BIOS hooks
[edit]DOS
[edit]On DOS systems, IO.SYS or IBMBIO.COM hooks INT 13 for floppy disk change detection, tracking formatting calls, correcting DMA boundary errors, and working around problems in IBM's ROM BIOS "01/10/84" with model code 0xFC before the first call.
Bypassing BIOS
[edit]Many modern operating systems (such as Linux and Windows) do not use any BIOS interrupt calls at all after startup, instead choosing to directly interface with the hardware. To do this, they rely upon drivers that are either a part of the OS kernel itself, ship along with the OS, or are provided by hardware vendors.
There are several reasons for this practice. Most significant is that modern operating systems run with the processor in protected (or long) mode, whereas the BIOS code will only execute in real mode. This means that if an OS running in protected mode wanted to make a BIOS call, it would have to first switch into real mode, then execute the call and wait for it to return, and finally switch back to protected mode. This would be terribly slow and inefficient. Code that runs in real mode (including the BIOS) is limited to accessing just over 1 MiB of memory, due to using 16-bit segmented memory addressing. Additionally, the BIOS is generally not the fastest way to carry out any particular task. In fact, the speed limitations of the BIOS made it common even in the DOS era for programs to circumvent it in order to avoid its performance limitations, especially for video graphics display and fast serial communication.
Beyond the above factors, problems with BIOS functionality include limitations in the range of functions defined, inconsistency in the subsets of those functions supported on different computers, and variations in the quality of BIOSes (i.e. some BIOSes are complete and reliable, others are abridged and buggy). By taking matters into their own hands and avoiding reliance on BIOS, operating system developers can eliminate some of the risks and complications they face in writing and supporting system software. On the other hand, by doing so those developers become responsible for providing "bare-metal" driver software for every different system or peripheral device they intend for their operating system to work with (or for inducing the hardware producers to provide those drivers).
Thus it should be apparent that compact operating systems developed on small budgets would tend to use BIOS heavily, while large operating systems built by huge groups of software engineers with large budgets would more often opt to write their own drivers instead of using BIOS—that is, even without considering the compatibility problems of BIOS and protected mode.
See also
[edit]Notes
[edit]- ^ Not all computers with BIOS are IBM PC compatible
References
[edit]- ^ "Booting · Linux Inside". 0xax.gitbooks.io. Retrieved 2020-11-10.
- ^ "Grub2 Booting Process". 21 June 2016.
- ^ * BIOS Boot Specification Version 1.01 January 11 1996 Appendix D
- The x86 Interrupt List (a.k.a. RBIL, Ralf Brown's Interrupt List)
- Embedded BIOS User's Manual
- PhoenixBIOS 4.0 User's Manual
- IBM Personal System/2 and Personal Computer BIOS Interface Technical Reference, IBM, 1988, OCLC 20737442
- System BIOS for IBM PCs, Compatibles, and EISA Computers, Phoenix Technologies, 1991, ISBN 0201577607
- Programmer's Guide to the AMIBIOS, American Megatrends, 1993, ISBN 0070015619
- The Programmer's PC Sourcebook by Thom Hogan, Microsoft Press, 1991 ISBN 155615321X
BIOS interrupt call
View on GrokipediaFundamentals of BIOS Interrupts
Purpose and Role in System Boot
The Basic Input/Output System (BIOS) serves as firmware embedded in the read-only memory (ROM) of the IBM Personal Computer, introduced in 1981, to initialize essential hardware components upon power-on and provide a layer of abstraction for software accessing those components. By offering standardized services through interrupt calls, the BIOS enables operating systems and applications to interact with hardware without needing to implement device-specific programming, thereby simplifying software development and ensuring compatibility across varying hardware configurations.[1] In the system boot process, the BIOS executes the Power-On Self-Test (POST) to verify and initialize critical elements such as the central processing unit, memory, direct memory access controllers, timers, and interrupt controllers, confirming operational integrity before proceeding. Following successful POST completion, the BIOS establishes the interrupt vector table and populates it with addresses for its service routines, preparing the system for handover to the bootstrap loader or operating system, which then assumes control from the boot sector loaded into memory. This structured initialization ensures a reliable transition from firmware to the loaded software environment.[1] The use of interrupt calls in BIOS confers key benefits, including enhanced portability by standardizing access to hardware functions like character output to displays and reads from disk storage, allowing software to operate consistently despite underlying variations in peripherals. Additionally, BIOS routines incorporate error handling mechanisms, returning status codes in designated registers to indicate success or failure—such as setting a carry flag for errors—enabling calling programs to detect and respond to issues like data integrity problems during operations. These features collectively support robust system bootstrapping and ongoing hardware interaction in early personal computing architectures.[1]Historical Development and Evolution
The BIOS interrupt call mechanism originated with the introduction of the IBM Personal Computer (Model 5150) in August 1981, where the ROM-based Basic Input/Output System (BIOS) provided a standardized set of software interrupts to abstract hardware access for operating systems and applications.[1] This design drew conceptual inspiration from the Basic Input/Output System in the CP/M operating system developed by Digital Research in 1975, which similarly served as a hardware abstraction layer, though CP/M primarily used direct calls rather than x86-style interrupts.[4] The initial IBM BIOS supported essential services such as video display (INT 10h), diskette I/O (INT 13h), keyboard input (INT 16h), and timekeeping (INT 1Ah), enabling portability across software while insulating it from underlying hardware variations.[1] Evolution accelerated with subsequent IBM models in the early 1980s, as the platform expanded to include fixed storage and advanced processors. The IBM PC XT (Model 5160), released in 1983, extended INT 13h functions to support hard disk operations, including reset, read, and write commands for up to four drives, addressing the growing need for non-volatile storage in business applications.[5] The IBM PC/AT (Model 5170), introduced in 1984 with the Intel 80286 processor, further refined these interrupts by incorporating enhanced error handling and parameter passing conventions, while Microsoft and IBM collaborated to standardize the interface through PC DOS, ensuring compatibility for third-party software development throughout the decade. Phoenix Technologies played a pivotal role in this era by developing the first clean-room implementation of a compatible BIOS in 1984, allowing non-IBM manufacturers to produce PC clones without infringing on proprietary code and thereby accelerating industry-wide adoption of the interrupt standards.[6] A significant milestone occurred in 1987 with the IBM Personal System/2 (PS/2) lineup, which introduced the Advanced BIOS (ABIOS) alongside traditional real-mode interrupts to support protected-mode multitasking and new hardware like the Micro Channel Architecture bus.[7] Enhancements included new subfunctions in INT 10h for video state management and palette control, expanded INT 13h capabilities for ESDI drives and head parking, and additions to INT 15h for extended memory sizing and mode switching, enabling better integration with operating systems like OS/2.[7] By the 1990s, the ecosystem had matured to define over 20 standard BIOS interrupts (primarily INT 08h through INT 1Fh), covering hardware events like timer ticks and device I/O, though original equipment manufacturers (OEMs) often added undocumented extensions that varied by vendor, complicating software portability. The prominence of BIOS interrupt calls began to wane in the mid-1990s as 32-bit operating systems gained traction. Windows 95 (1995) and subsequent versions increasingly bypassed BIOS routines in favor of direct hardware access through virtual device drivers (VxDs) and later Windows Driver Model (WDM) components, improving performance for graphics, disk, and network operations by avoiding the overhead of real-mode interrupts in protected-mode environments.[8] This shift marked the transition toward more sophisticated firmware like UEFI by the early 2000s, though legacy BIOS interrupts persisted for boot processes and compatibility in x86 systems.[9]Mechanism of BIOS Calls
Software Interrupt Instruction
In x86 architecture, the software interrupt instruction, denoted as INT n, serves as the primary mechanism for programs to invoke BIOS services in real mode. This instruction generates a software interrupt by specifying an 8-bit interrupt vector number n (ranging from 0 to 255), which directs the CPU to transfer control to the corresponding handler in the Interrupt Vector Table (IVT). BIOS interrupts specifically utilize the vector range from 10h to 1Fh, reserving these for system services such as video, disk, and keyboard operations, ensuring compatibility in the 16-bit real-address mode where BIOS firmware operates exclusively.[10][11] When executed, the INT n instruction first pushes the current state onto the stack to preserve the calling program's context: it saves the flags register (2 bytes in real mode), the code segment register CS (2 bytes), and the instruction pointer IP (2 bytes), totaling 6 bytes. The CPU then clears the interrupt flag (IF) and trap flag (TF) to disable maskable interrupts and single-step mode during handler execution, preventing nested interrupts unless explicitly re-enabled. Next, it fetches the 4-byte interrupt vector from the IVT—located at physical memory addresses 0000:0000 to 0000:03FF—using the offset 4 × n; this vector consists of a 16-bit offset (for IP) followed by a 16-bit segment (for CS). The CPU loads this CS:IP pair and jumps to the BIOS handler routine at that segment:offset address, using real-mode memory addressing where the effective address is calculated as (CS × 16) + IP.[11][11] The interrupt handling pipeline proceeds with the BIOS routine executing the requested service, after which it returns control to the caller via the IRET (interrupt return) instruction. IRET pops the saved IP, CS, and flags from the stack in reverse order, restoring the original processor state and resuming execution at the instruction following the INT n call. This ensures transparent context switching, with the entire process operating within real mode's 1 MB address space limitation and 64 KB segment boundaries. For assembly code representation, a typical BIOS call might appear as:MOV AH, 0Eh ; Function: Teletype output (example, not detailed here)
MOV AL, 'A' ; Character to output
INT 10h ; Invoke video BIOS
MOV AH, 0Eh ; Function: Teletype output (example, not detailed here)
MOV AL, 'A' ; Character to output
INT 10h ; Invoke video BIOS
Register Conventions and Parameter Passing
BIOS interrupt calls rely on standardized conventions for passing parameters and returning results through the x86 CPU registers, ensuring compatibility and predictability across different system implementations. These conventions were established in the original IBM PC BIOS design to facilitate interaction between application software and hardware services without relying on complex memory structures. Parameters are primarily exchanged via general-purpose registers, with the accumulator (AX) and major subregisters (AH, AL) playing central roles, as documented in IBM's official BIOS interface specifications.[7] For input parameters, the high byte of the accumulator (AH) is universally used to specify the function subcode, which selects the specific service within a given interrupt vector. Additional parameters are passed in other registers, such as the low byte of the accumulator (AL) for mode selections or the data register low byte (DL) for device identifiers, like drive numbers in disk operations. For instance, in disk I/O services, DL holds the drive number to target fixed or floppy disks. Other registers like CX and DX may carry count or address values, minimizing the need for stack-based passing to maintain efficiency in real-mode environments. These register-based inputs align with the 16-bit architecture constraints of early PCs.[7][2] Output conventions focus on the accumulator (AX) for primary return values, such as status codes or data results, allowing the caller to inspect outcomes directly after the interrupt returns. The carry flag (CF) serves as a binary status indicator, set to 0 for successful operations and 1 for failures or errors, providing a quick check without decoding complex values. Data buffers, when required, are addressed via segment:offset pairs like ES:BX, pointing to memory locations for read or write operations. This approach ensures that large data transfers use far pointers without altering the caller's segment assumptions excessively.[7][2] Segment registers such as DS and ES are employed for accessing memory blocks during parameter exchange, but BIOS routines are required to preserve them unless explicitly modified for output purposes, like setting ES for buffer segments. General-purpose registers beyond those used for inputs and outputs are preserved by the BIOS handler to avoid disrupting the caller's state, except for AX, the flags, and designated return registers. This preservation rule supports nested calls and maintains system stability.[7][2] To ensure backward compatibility with 8086 and 80286 processors, BIOS conventions avoid 32-bit register extensions, sticking to 16-bit operations even on later systems. Stack usage is kept minimal, primarily for interrupt context saving during execution, as parameters are register-based to prevent overflow in limited real-mode stacks. This design choice, rooted in the original PC architecture, allows efficient invocation via the INT instruction without heavy reliance on the stack segment.[7][2]Interrupt Vector Table
Structure and Memory Location
The Interrupt Vector Table (IVT) in x86 real mode is a fixed 1 KB data structure located at physical memory address 00000h:00000h, spanning from offset 0000h to 03FFh.[2][14] It consists of 256 contiguous entries, one for each possible interrupt vector from 00h to FFh, with each entry occupying exactly 4 bytes to store a far pointer to the corresponding interrupt handler routine.[2][14] Each IVT entry follows a standardized format: the first two bytes (low word) hold the 16-bit offset address within the code segment where the handler begins, while the next two bytes (high word) contain the 16-bit segment address of the handler's code segment.[2][14] To access an entry, the processor multiplies the interrupt number by 4 to compute the starting offset in the table; for example, interrupt 10h resides at offset 0028h (10h × 4 = 28h).[14] This segment:offset pair forms a 20-bit physical address in real mode, enabling jumps to handlers anywhere in the 1 MB address space.[2] In the context of BIOS operations, the IVT entries for vectors 10h through 1Fh are specifically populated to point to handler routines residing in the system ROM, typically mapped to the upper memory range F0000h to FFFFFh.[2] These vectors support core BIOS services such as video display (10h), equipment configuration (11h), memory sizing (12h), disk I/O (13h), serial communications (14h), miscellaneous system functions (15h), keyboard input (16h), printer output (17h), BASIC entry (18h), bootstrap loading (19h), and timer/clock services (1Ah), with 1Bh to 1Fh reserved for future or system-specific use.[2] For instance, the INT 10h vector at IVT offset 0028h might point to F000:E6F5, directing execution to the video handler in ROM.[2] The IVT is initially populated during the Power-On Self-Test (POST) phase of the BIOS boot process, where the firmware copies the appropriate segment:offset addresses from predefined locations in ROM to the low-memory table entries, ensuring hardware and software interrupts can invoke BIOS services immediately after initialization.[2] However, once the operating system loads during boot, it typically overwrites significant portions of the IVT—including BIOS vectors—to install its own interrupt handlers, redirecting control to OS-managed routines while preserving compatibility for any remaining BIOS calls.[15][2] This transition marks the handover from firmware to the loaded OS, though the original BIOS setup remains critical for early boot stages.[15]Population and Initialization Process
During the Power-On Self-Test (POST), the BIOS initiates the population of the Interrupt Vector Table (IVT) by first establishing initial vectors, including CPU exception handlers from 00h to 07h, hardware interrupt handlers from the master PIC from 08h to 0Fh, and BIOS software service vectors from 10h to 1Fh, directing them to core BIOS routines for essential functions such as the system timer (INT 08h) and keyboard input (INT 09h).[2] This step occurs early in the POST sequence to ensure basic hardware responsiveness before further system configuration.[16] Following hardware vector setup, the BIOS performs a scan of the upper memory ROM space, typically from C0000h to EFFFFh, in 2 KB segments, to detect option ROMs from add-in cards and peripherals. For each potential ROM segment, the BIOS computes a checksum by summing all bytes and verifying it against a stored value (often the last byte or a dedicated checksum byte); a valid checksum triggers execution of the ROM's initialization code, which may install or update interrupt vectors, especially for BIOS services in the 10h to 1Fh range, such as video services (INT 10h) or disk operations (INT 13h).[17] Software interrupt vectors from 20h onward are populated later in this process, after ROM scanning and hardware initialization, allowing extensions without conflicting with core vectors.[16] The 8259 Programmable Interrupt Controllers (PICs)—one master for IRQs 0-7 and one slave for IRQs 8-15—are also initialized during POST to support vectored interrupts. The BIOS issues Initialization Command Words (ICWs) to both PICs via their I/O ports (20h/21h for master, A0h/A1h for slave), configuring the master to recognize the slave on its IRQ 2 line through ICW3 (setting bit 2), thereby chaining slave interrupts to flow through the master before reaching the CPU.[18] Upon loading MS-DOS as the operating system, the IVT undergoes further modification as DOS installs its own handlers in designated slots, such as INT 20h for program termination and INT 21h for DOS services, while preserving or chaining to BIOS vectors (e.g., 10h-1Fh) to enable applications to access underlying hardware services without direct BIOS calls.[19] This takeover ensures DOS compatibility with the existing IVT structure at memory location 00000h.[20]Key BIOS Interrupt Services
Video Display Functions (INT 10h)
The BIOS interrupt INT 10h provides essential services for video display operations in x86-based systems, enabling software to manage text and graphics modes, cursor control, and character output without direct hardware access.[2] These functions were integral to early PC graphics, supporting operations across adapters like CGA, EGA, and VGA.[21] Key subfunctions include setting video modes, positioning the cursor, and outputting characters via teletype-style routines, with parameters passed primarily through CPU registers such as AH for the function selector, AL for mode or character data, BH for display page, and DH/DL for cursor coordinates.[22] One fundamental service is AH=00h, which sets the video mode and clears the screen. Input requires AL to specify the mode number; for example, AL=03h selects 80x25 color text mode with 16 colors, while AL=06h enables 640x200 monochrome graphics.[2] This function initializes the display adapter, mapping video memory to segments like B8000h for text or A0000h for graphics, but early implementations were limited to resolutions such as 80 columns by 25 rows for text and a maximum of 640x200 pixels for CGA graphics modes.[21] No return values are provided, and the operation relies on the installed hardware capabilities.[22] For character output, AH=0Eh performs teletype output to the active display page. It takes AL as the ASCII character to display, BH as the page number (typically 0 for single-page displays), and optionally BL as the foreground color in graphics modes.[2] The routine writes the character at the current cursor position, advances the cursor, and handles control codes like carriage return (0Dh), line feed (0Ah), backspace (08h), and bell (07h) by scrolling the screen if necessary or adjusting position accordingly.[21] This service ensures compatibility with text-based interfaces but is constrained to the active mode's character set and does not support advanced formatting.[22] Cursor manipulation is handled by AH=02h, which sets the cursor position on a specified display page. Inputs include BH for the page number, DH for the row (0-24 in 25-row modes), and DL for the column (0-79 in 80-column modes).[2] The function immediately updates the cursor without returning values, though a companion service (AH=03h) can retrieve the current position in BH (page), DH (row), and DL (column).[21] These coordinates are zero-based from the upper-left corner, supporting multi-page displays in text modes but limited to the resolution of the current video mode.[22] Early BIOS implementations for CGA and MDA adapters imposed significant limitations, restricting text to 80x25 grids and graphics to 640x200 resolutions with fixed 2- or 4-color palettes, and lacking support for dynamic color adjustments.[2] No palette modifications were possible pre-VGA, as colors were hardware-defined without BIOS-accessible registers.[21] With the introduction of EGA and VGA hardware in 1987 via IBM's PS/2 systems, extensions under AH=10h through AH=12h were added to the INT 10h handler, enabling palette register manipulation for up to 256 simultaneous colors from a 262,144-color space, along with character generator loading and alternate mode selections.[2] These enhancements, such as AH=10h for setting individual RGB palette values, greatly expanded graphical capabilities while maintaining backward compatibility.[22]| Function | AH Value | Key Inputs | Behavior | Example Mode/Use |
|---|---|---|---|---|
| Set Video Mode | 00h | AL = mode (e.g., 03h) | Initializes display, clears screen | 80x25 text (AL=03h); 640x200 graphics (AL=06h) |
| Teletype Output | 0Eh | AL = char, BH = page, BL = color (graphics) | Writes char, advances cursor, handles controls | Display 'A' on page 0 |
| Set Cursor Position | 02h | BH = page, DH = row, DL = col | Moves cursor to specified location | Position to row 10, col 20 on page 0 |
Disk I/O Operations (INT 13h)
The INT 13h interrupt handler provides low-level access to floppy diskettes and fixed hard disks in x86-based systems, enabling read and write operations through the BIOS without relying on higher-level operating system services.[2] It uses Cylinder-Head-Sector (CHS) addressing, where the cylinder (CH) specifies the track position, the head (DH) selects the disk surface, and the sector (CL) identifies the data block within the track, typically 512 bytes per sector.[2] The drive number is passed in DL, with bit 7 set for hard disks and clear for floppies; data buffers are specified via ES:BX.[2] Operations return success in AL=00h or errors such as AL=02h for a bad sector, with the carry flag (CF) set on failure.[2] For reading sectors, the AH=02h function transfers data from the disk to memory.[2] Input parameters include AL for the number of sectors (up to the drive's maximum per track), CH for the low 8 bits of the cylinder (0-1023), CL where bits 0-5 hold the starting sector (1-based) and bits 6-7 the high 2 bits of the cylinder, DH for the head (0-255), DL for the drive, and ES:BX pointing to the destination buffer.[2] On success, AL holds the actual sectors read; errors may trigger automatic resets and retries by the BIOS.[2] Writing sectors uses AH=03h with identical inputs, except the buffer contains data to write, and it supports optional verification.[2] To retrieve drive geometry, AH=08h queries parameters for a specified drive in DL.[2] Outputs include DH for maximum heads, CH for low 8 bits of maximum cylinders, CL encoding maximum sectors per track (bits 0-5) and high 2 bits of maximum cylinders (bits 6-7), and DL for the number of attached drives; some implementations also return a parameter table pointer in ES:DI.[2] This function is essential for initializing CHS-based operations and supports both floppy and hard disk geometries.[2] CHS addressing imposes limits, such as a maximum of 1024 cylinders, 256 heads, and 63 sectors per track for hard disks, equating to about 7.8 GB addressable space before extensions.[23] For floppies, BIOS implementations typically support formats up to 1.44 MB (80 cylinders, 2 heads, 18 sectors), though early systems were constrained to smaller capacities like 360 KB due to controller and media limitations.[2] Logical Block Addressing (LBA) conversion from CHS is handled by the BIOS in extended modes, mapping linear block numbers to physical locations for larger drives.[23] In the 1990s, INT 13h extensions addressed these constraints for drives exceeding 8 GB, introducing LBA support via functions like AH=41h for installation check.[23] This check uses BX=55AAh on entry and returns BX=AA55h with AH=30h if supported, indicating features like extended disk access.[23] Extended read (AH=42h) and write (AH=43h) use a disk address packet at DS:SI, specifying 64-bit LBA and sector count, transferring up to 127 sectors per call.[23] AH=48h provides enhanced parameters, including total sectors and LBA mode support, enabling capacities up to 2^64 sectors.[23] These extensions, part of the Enhanced Disk Drive (EDD) specification, maintain backward compatibility while overcoming CHS barriers.[23]Keyboard and System Services (INT 16h and INT 1Ah)
The BIOS interrupt 16h provides essential services for handling keyboard input in IBM PC-compatible systems, enabling software to read keystrokes and check buffer status without direct hardware access. This interrupt interfaces with a 16-entry keyboard buffer in system RAM at address 0040:001E, where each entry stores a 16-bit value with the low byte as the ASCII character code and the high byte as the scan code for non-ASCII keys. The buffer is managed using head and tail pointers at 0040:001A and 0040:001C, respectively, and is populated by the keyboard interrupt handler (INT 09h). Shift and modifier states, such as Caps Lock, Num Lock, Scroll Lock, Ctrl, Alt, and Shift keys, are tracked in a byte at 0040:0017, allowing the BIOS to generate appropriate ASCII codes based on key combinations.[24] To read a key, software invokes INT 16h with AH set to 00h, which blocks until a keystroke is available. On AT and later systems, before waiting, the BIOS issues INT 15h with AH=90h to allow the operating system to yield control, supporting basic multitasking. It then returns the scan code in AH and the ASCII code in AL, removing the entry from the buffer. For non-destructive checking, AH=01h is used: if a key is available (zero flag clear), it returns the scan and ASCII codes without dequeuing; otherwise, the zero flag is set to indicate an empty buffer. These functions support extended keys (e.g., function keys or arrows) by generating make/break scan codes, ensuring compatibility for text-based applications like early DOS programs that relied on polled input rather than event-driven methods. The design prioritizes simplicity, buffering up to 15 keystrokes to handle burst input while maintaining low overhead for real-time responsiveness.[24] BIOS interrupt 1Ah delivers timekeeping services, allowing access to both system timer counts and real-time clock (RTC) data stored in CMOS RAM. With AH=00h, it returns a 32-bit tick count in CX:DX representing the number of interrupts since midnight, providing a coarse timing mechanism updated approximately 86,400 times per day. The AH=02h function reads the RTC time in binary-coded decimal (BCD) format, returning hours in CH, minutes in CL, seconds in DH, and a daylight savings flag in DL; this data is mirrored in system RAM at 0040:006C for faster access. These services are driven by the 18.2 Hz timer interrupt from IRQ 0, generated by the Intel 8253/8254 Programmable Interval Timer (PIT) at I/O port 0040h, which increments the tick counter and supports basic elapsed time calculations for applications like scheduling or animations in legacy environments.[24] Interrupt 11h retrieves the system's equipment configuration list, returning a 16-bit word in AX that encodes hardware presence and counts, initialized during POST and stored at 0040:0010. Key bits include 7-6 for the number of floppy disk drives (00b for one, up to 11b for four), 11-9 for serial ports, 15-14 for parallel printer adapters (00b for none, up to 11b for three), bit 0 for floppy disk installed, bit 1 for math coprocessor, bit 2 for pointing device, and bits 5-4 for video adapter type (e.g., 00b for color/graphics). This information enables software to adapt to varying hardware setups, such as querying available drives before I/O operations or detecting printers for output routing, without scanning hardware directly. For example, a program might use this to determine if a second floppy drive is present for dual-sided media handling. The interrupt vector for these services resides in the low 1KB of RAM, as detailed in the Interrupt Vector Table section.[24]| Bit Position | Description | Encoding Example |
|---|---|---|
| 15-14 | Number of printer adapters | 00b: 0, 01b: 1, 10b: 2, 11b: 3 |
| 11-9 | Number of serial adapters | Varies (e.g., 000b: 0 ports) |
| 7-6 | Number of floppy drives | 00b: 1, 01b: 2, 10b: 3, 11b: 4 |
| 5-4 | Video display type | 00b: Color 80x25, 01b: Monochrome 80x25 |
| 2 | Pointing device present | 0: Absent, 1: Present |
| 1 | Math coprocessor present | 0: Absent, 1: Present |
| 0 | Floppy disk installed | 0: No, 1: Yes |
