Hubbry Logo
BIOS interrupt callBIOS interrupt callMain
Open search
BIOS interrupt call
Community hub
BIOS interrupt call
logo
7 pages, 0 posts
0 subscribers
Be the first to start a discussion here.
Be the first to start a discussion here.
BIOS interrupt call
BIOS interrupt call
from Wikipedia

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
AH Description
00h Set Video Mode
01h Set Cursor Shape
02h Set Cursor Position
03h Get Cursor Position And Shape
04h Get Light Pen Position
05h Set Display Page
06h Clear/Scroll Screen Up
07h Clear/Scroll Screen Down
08h Read Character and Attribute at Cursor
09h Write Character and Attribute at Cursor
0Ah Write Character at Cursor
0Bh Set Border Color
0Ch Write Graphics Pixel
0Dh Read Graphics Pixel
0Eh Write Character in TTY Mode
0Fh Get Video Mode
10h Set Palette Registers (EGA, VGA, SVGA)
11h Character Generator (EGA, VGA, SVGA)
12h Alternate Select Functions (EGA, VGA, SVGA)
13h Write String
1Ah Get or Set Display Combination Code (VGA, SVGA)
1Bh Get Functionality Information (VGA, SVGA)
1Ch Save or Restore Video State (VGA, SVGA)
4Fh VESA BIOS Extension Functions (SVGA)
11h Returns equipment list
12h Return conventional memory size
13h Low Level Disk Services
AH Description
00h Reset Disk Drives
01h Check Drive Status
02h Read Sectors
03h Write Sectors
04h Verify Sectors
05h Format Track
08h Get Drive Parameters
09h Init Fixed Drive Parameters
0Ch Seek To Specified Track
0Dh Reset Fixed Disk Controller
15h Get Drive Type
16h Get Floppy Drive Media Change Status
17h Set Disk Type
18h Set Floppy Drive Media Type
41h Extended Disk Drive (EDD) Installation Check
42h Extended Read Sectors
43h Extended Write Sectors
44h Extended Verify Sectors
45h Lock/Unlock Drive
46h Eject Media
47h Extended Seek
48h Extended Get Drive Parameters
49h Extended Get Media Change Status
4Eh Extended Set Hardware Configuration
14h Serial port services
AH Description
00h Serial Port Initialization
01h Transmit Character
02h Receive Character
03h Status
15h Miscellaneous system services
AH AL Description
00h Turn on cassette drive motor (IBM PC/PCjr only)
01h Turn off cassette drive motor (IBM PC/PCjr only)
02h Read data blocks from cassette (IBM PC/PCjr only)
03h Write data blocks to cassette (IBM PC/PCjr only)
4Fh Keyboard Intercept
83h Event Wait
84h Read Joystick (BIOSes from 1986 onward)
85h Sysreq Key Callout
86h Wait
87h Move Block
88h Get Extended Memory Size
89h Switch to Protected Mode
C0h Get System Parameters
C1h Get Extended BIOS Data Area Segment
C2h Pointing Device Functions
C3h Watchdog Timer Functions - PS/2 systems only
C4h Programmable Option Select - MCA bus PS/2 systems only
D8h EISA System Functions - EISA bus systems only
E8h 01h Get Extended Memory Size (Newer function, since 1994). Gives results for memory size above 64 Mb.
E8h 20h Query System Address Map. The information returned from E820 supersedes what is returned from the older AX=E801h and AH=88h interfaces.
16h Keyboard services
AH Description
00h Read Character
01h Read Input Status
02h Read Keyboard Shift Status
05h Store Keystroke in Keyboard Buffer
10h Read Character Extended
11h Read Input Status Extended
12h Read Keyboard Shift Status Extended
17h Printer services
AH Description
00h Print Character to Printer
01h Initialize Printer
02h Check Printer Status
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
AH Description
00h Read RTC
01h Set RTC
02h Read RTC Time
03h Set RTC Time
04h Read RTC Date
05h Set RTC Date
06h Set RTC Alarm
07h Reset RTC Alarm
1Ah PCI Services - implemented by BIOSes supporting PCI 2.0 or later
AX Description
B101h PCI Installation Check
B102h Find PCI Device
B103h Find PCI Class Code
B106h PCI Bus-Specific Operations
B108h Read Configuration Byte
B109h Read Configuration Word
B10Ah Read Configuration Dword
B10Bh Write Configuration Byte
B10Ch Write Configuration Word
B10Dh Write Configuration Dword
B10Eh Get IRQ Routine Information
B10Fh Set PCI IRQ
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]

References

[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
A BIOS interrupt call is a software interrupt mechanism in x86-based personal computers that allows operating systems and applications to invoke routines within the Basic Input/Output System (), a layer stored in (ROM) on the . Originating with the Personal Computer in 1981, these calls provide a standardized interface for accessing hardware services such as video display control, keyboard input, disk operations, and printer output, abstracting low-level hardware details to ensure and compatibility across IBM PC-compatible systems. To execute a BIOS interrupt call, a program sets the function code in the AH register of the CPU (e.g., AH=00h to set video mode) and issues an INT instruction followed by the specific vector number, such as for video services or for diskette and fixed-disk operations. The routine, located in the system's ROM, then processes the request using parameters passed via CPU registers like AL, BX, CX, and DX, returning results in the same registers while preserving others to maintain program state. This register-based parameter passing and the use of the at 00000h enable efficient, hardware-agnostic interactions without direct or access. Notable BIOS interrupts encompass a range of essential functions, including for comprehensive video I/O (e.g., cursor positioning and character writing), for disk sector read/write and formatting, INT 14h for asynchronous serial communications, for keyboard buffer reads, INT 17h for parallel printer control, and INT 1Ah for system timer and services. These interrupts were foundational for early software ecosystems, such as applications and bootloaders, by handling both character- and block-level I/O while supporting multitasking hooks and equipment configuration queries like memory size via INT 12h. In modern computing, BIOS interrupt calls persist primarily as a legacy feature within (UEFI) systems, where the Compatibility Support Module (CSM) emulates the 16-bit real-mode environment through mode-switching thunks and protocols like EFI_LEGACY_BIOS_PROTOCOL.Int86() to execute traditional interrupts such as or . This support ensures for older operating systems, option ROMs, and boot processes, though contemporary OSes like Windows and bypass them in favor of protected-mode drivers and direct hardware access for performance and security reasons.

Fundamentals 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. In the system boot process, the executes the () to verify and initialize critical elements such as the , , controllers, timers, and interrupt controllers, confirming operational integrity before proceeding. Following successful POST completion, the establishes the 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 . This structured initialization ensures a reliable transition from to the loaded software environment. 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 , 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 for errors—enabling calling programs to detect and respond to issues like problems during operations. These features collectively support robust system and ongoing hardware interaction in early personal computing architectures.

Historical Development and Evolution

The BIOS interrupt call mechanism originated with the introduction of the 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. This design drew conceptual inspiration from the Basic Input/Output System in the operating system developed by in 1975, which similarly served as a layer, though primarily used direct calls rather than x86-style interrupts. The initial BIOS supported essential services such as video display (), diskette I/O (), keyboard input (), and timekeeping (INT 1Ah), enabling portability across software while insulating it from underlying hardware variations. Evolution accelerated with subsequent models in the early 1980s, as the platform expanded to include fixed storage and advanced processors. The PC XT (Model 5160), released in 1983, extended 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. The PC/AT (Model 5170), introduced in 1984 with the processor, further refined these interrupts by incorporating enhanced error handling and parameter passing conventions, while and collaborated to standardize the interface through PC DOS, ensuring compatibility for third-party software development throughout the decade. played a pivotal role in this era by developing the first clean-room implementation of a compatible in 1984, allowing non- manufacturers to produce PC clones without infringing on proprietary code and thereby accelerating industry-wide adoption of the interrupt standards. A significant milestone occurred in 1987 with the 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 bus. Enhancements included new subfunctions in for video state management and palette control, expanded 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. By the , 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. (1995) and subsequent versions increasingly bypassed 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 s in protected-mode environments. This shift marked the transition toward more sophisticated firmware like by the early 2000s, though legacy interrupts persisted for boot processes and compatibility in x86 systems.

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 services in . This instruction generates a software by specifying an 8-bit vector number n (ranging from 0 to 255), which directs the CPU to transfer control to the corresponding handler in the (IVT). 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 firmware operates exclusively. 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. 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 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

Error handling in BIOS interrupts follows a standardized convention: upon failure, the routine sets the carry flag (CF = 1) and loads the AH register (high byte of AX) with a specific error code, such as 01h indicating an invalid function subcode. The caller must check CF post-return (e.g., via JC for jump if carry set) to detect errors, with AL often preserving input parameters or providing additional status. This mechanism allows robust error detection without altering other registers unnecessarily, though success typically clears CF (CF = 0) and sets AH to 00h or a success indicator.

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 PC BIOS design to facilitate interaction between application software and hardware services without relying on complex memory structures. are primarily exchanged via general-purpose registers, with the accumulator (AX) and major subregisters (AH, AL) playing central roles, as documented in 's official BIOS interface specifications. 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 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 constraints of early PCs. Output conventions focus on the accumulator (AX) for primary return values, such as status codes or results, allowing the caller to inspect outcomes directly after the interrupt returns. The (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. buffers, when required, are addressed via segment:offset pairs like ES:BX, pointing to locations for read or write operations. This approach ensures that large data transfers use far pointers without altering the caller's segment assumptions excessively. Segment registers such as DS and are employed for accessing memory blocks during parameter exchange, but 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. To ensure 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 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.

Interrupt Vector Table

Structure and Memory Location

The Interrupt Vector Table (IVT) in x86 is a fixed 1 KB data structure located at physical 00000h:00000h, spanning from offset 0000h to 03FFh. 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 routine. Each IVT entry follows a standardized format: the first two bytes (low word) hold the 16-bit offset address within the where the handler begins, while the next two bytes (high word) contain the 16-bit segment address of the handler's . To access an entry, the processor multiplies the number by 4 to compute the starting offset in the table; for example, 10h resides at offset 0028h (10h × 4 = 28h). This segment:offset pair forms a 20-bit in , enabling jumps to handlers anywhere in the 1 MB address space. 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. 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. For instance, the INT 10h vector at IVT offset 0028h might point to F000:E6F5, directing execution to the video handler in ROM. 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. 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. This transition marks the handover from firmware to the loaded OS, though the original BIOS setup remains critical for early boot stages.

Population and Initialization Process

During the Power-On Self-Test (POST), the BIOS initiates the population of the (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 (INT 08h) and keyboard input (INT 09h). This step occurs early in the POST sequence to ensure basic hardware responsiveness before further system configuration. Following hardware vector setup, the BIOS performs a scan of the upper 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 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 vectors, especially for BIOS services in the 10h to 1Fh range, such as video services () or disk operations (). Software vectors from 20h onward are populated later in this process, after ROM scanning and hardware initialization, allowing extensions without conflicting with core vectors. The 8259 Programmable Interrupt Controllers (PICs)—one master for IRQs 0-7 and one slave for IRQs 8-15—are also initialized during to support vectored interrupts. The 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. Upon loading 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 services, while preserving or chaining to vectors (e.g., 10h-1Fh) to enable applications to access underlying hardware services without direct calls. This takeover ensures compatibility with the existing IVT structure at memory location 00000h.

Key BIOS Interrupt Services

Video Display Functions (INT 10h)

The BIOS interrupt provides essential services for video display operations in x86-based systems, enabling software to manage text and modes, cursor control, and character output without direct hardware access. These functions were integral to early PC , supporting operations across adapters like CGA, EGA, and VGA. 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. 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 . This function initializes the display adapter, mapping video memory to segments like B8000h for text or A0000h for , but early implementations were limited to resolutions such as 80 columns by 25 rows for text and a maximum of 640x200 pixels for CGA modes. No return values are provided, and the operation relies on the installed hardware capabilities. 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. 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. This service ensures compatibility with text-based interfaces but is constrained to the active mode's character set and does not support advanced formatting. 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). 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). 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. 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. No palette modifications were possible pre-VGA, as colors were hardware-defined without BIOS-accessible registers. 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 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. These enhancements, such as AH=10h for setting individual RGB palette values, greatly expanded graphical capabilities while maintaining .
FunctionAH ValueKey InputsBehaviorExample Mode/Use
Set Video Mode00hAL = mode (e.g., 03h)Initializes display, clears screen80x25 text (AL=03h); 640x200 graphics (AL=06h)
Teletype Output0EhAL = char, BH = page, BL = color (graphics)Writes char, advances cursor, handles controlsDisplay 'A' on page 0
Set Cursor Position02hBH = page, DH = row, DL = colMoves cursor to specified locationPosition to row 10, col 20 on page 0

Disk I/O Operations (INT 13h)

The interrupt handler provides low-level access to floppy diskettes and fixed hard disks in x86-based systems, enabling read and write operations through the without relying on higher-level operating system services. It uses (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. 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. Operations return success in AL=00h or errors such as AL=02h for a , with the (CF) set on failure. For reading sectors, the AH=02h function transfers data from the disk to . 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. On success, AL holds the actual sectors read; errors may trigger automatic resets and retries by the . Writing sectors uses AH=03h with identical inputs, except the buffer contains data to write, and it supports optional verification. To retrieve drive geometry, AH=08h queries parameters for a specified drive in DL. 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. This function is essential for initializing CHS-based operations and supports both floppy and hard disk geometries. CHS addressing imposes limits, such as a maximum of cylinders, 256 heads, and 63 sectors per track for hard disks, equating to about 7.8 GB addressable space before extensions. 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. (LBA) conversion from CHS is handled by the BIOS in extended modes, mapping linear block numbers to physical locations for larger drives. In the 1990s, extensions addressed these constraints for drives exceeding 8 GB, introducing LBA support via functions like AH=41h for installation check. This check uses BX=55AAh on entry and returns BX=AA55h with AH=30h if supported, indicating features like extended disk access. Extended read (AH=42h) and write (AH=43h) use a disk packet at DS:SI, specifying 64-bit LBA and sector count, transferring up to 127 sectors per call. AH=48h provides enhanced parameters, including total sectors and LBA mode support, enabling capacities up to 2^64 sectors. These extensions, part of the Enhanced Disk Drive (EDD) specification, maintain while overcoming CHS barriers.

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. To read a key, software invokes with AH set to 00h, which blocks until a keystroke is available. On AT and later systems, before waiting, the 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 ( clear), it returns the scan and ASCII codes without dequeuing; otherwise, the 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. 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. Interrupt 11h retrieves the system's equipment configuration list, returning a 16-bit word in AX that encodes hardware presence and counts, initialized during 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 , 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 , 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 section.
Bit PositionDescriptionEncoding Example
15-14Number of printer adapters00b: 0, 01b: 1, 10b: 2, 11b: 3
11-9Number of serial adaptersVaries (e.g., 000b: 0 ports)
7-6Number of floppy drives00b: 1, 01b: 2, 10b: 3, 11b: 4
5-4Video display type00b: Color 80x25, 01b: 80x25
2 present0: Absent, 1: Present
1Math present0: Absent, 1: Present
0 installed0: No, 1: Yes

ROM BASIC Execution (INT 18h)

The INT 18h serves as the to the ROM-resident BASIC interpreter on early PC systems, transferring control directly to the Cassette BASIC implementation located at F600:0000. This interpreter, an enhanced variant of Microsoft's BASIC-80 without diskette support, occupies 8 KB within the 40 KB system ROM on the and enables users to write and execute BASIC programs using cassette tapes for storage and retrieval. No input parameters are required; invoking the simply initializes the BASIC environment, displaying the familiar "IBM BASIC" prompt (version C1.00 or later). In operational context, INT 18h takes precedence during the system boot sequence when the BIOS (POST) and bootstrap loader fail to locate bootable media, such as after checking the cassette interface first if equipped. If the equipment flag indicates no diskette drive (bit 0 = 0) and no valid Initial Program Load (IPL) is found, the BIOS automatically executes INT 18h to provide a fallback programming environment, allowing immediate interaction without an operating system. The interpreter supports basic I/O operations, including cassette read/write via dedicated BIOS routines, and reserves specific low-memory areas for its workspace and variables. Upon user initiation of the command within BASIC, control returns to the calling program, restoring the prior execution context without altering registers or stack beyond BASIC's internal setup. This mechanism ensured compatibility for standalone use but was limited to IBM-branded systems, as many PC clones omitted ROM BASIC entirely. By the late 1980s, with the series and widespread adoption of disk-based BASIC variants like (a self-contained executable bundled with that leverages but does not require the ROM routines), the need for embedded Cassette BASIC diminished; it was phased out in new IBM hardware by the early 1990s due to licensing changes with and the standardization of floppy drives. Today, ROM BASIC execution via INT 18h is preserved through emulation in virtual machines such as PCem and , enabling accurate reproduction of original PC behavior for historical and retro computing.

BIOS Extensions and System Integration

Hook Chains in Upper Memory

In IBM PS/2 BIOS systems, interrupt hook chains enable extensibility by allowing additional handlers to intercept and extend existing interrupt services without directly modifying the Interrupt Vector Table (IVT). Prior to PS/2, add-in cards and extensions typically hooked interrupts by directly updating entries in the IVT, saving and restoring the original vector to maintain chaining. A new handler begins by saving the original interrupt vector—typically in the first few bytes of its code segment—preserving the address of the prior routine. It then performs its custom operations before chaining to the original handler using a JMP instruction, ensuring sequential execution of all linked routines. This mechanism, detailed in the interrupt sharing specifications, includes a standardized 16-byte structure that must begin at the third byte of the handler code: a 4-byte FPTR (offset 0 within structure) to the next handler, followed by a 2-byte signature at offset 4 (e.g., 424Bh for non-ROM handlers) and 8 reserved bytes at offset 6. For ROM-based handlers, the signature 0000h is placed at offset 7 of the structure. Original equipment manufacturers (OEMs) commonly install these hook chains in upper memory blocks (UMBs), particularly the system ROM area from F0000h to FFFFFh, to integrate custom extensions such as drivers that augment disk I/O interrupts like . This placement leverages the reserved ROM space on the system board, scanned during for adapter modules, allowing handlers to link into services without conflicting with . For instance, controllers use this approach to insert their routines early in the chain, handling specialized commands before passing control to the standard disk functions. To detect and query upper memory configurations supporting these hooks, software invokes INT 15h with AH set to C0h, which returns a pointer in ES:BX to the system configuration parameters, including model details, submodel, revision, and references to ROM data areas. The PS/2 (ABI), standardized by in 1987, formalized this protocol across platforms, emphasizing vector preservation to prevent IVT overwrites and ensure reliable multi-vendor compatibility.

Interactions with DOS and Early OSes

The boot process for begins with the invoking interrupt 19h to load the operating system's from a storage device, typically a or hard drive, into memory at 0x7C00 before transferring control to it. Once loaded, initializes its core components, including the DOS kernel (MSDOS.SYS or equivalent), and establishes its own interrupt handlers, notably hooking interrupt 21h to provide higher-level services that abstract and extend functionality for tasks such as file . This layering allows DOS to intercept and manage hardware access through calls (e.g., for disk operations) while adding features like support and error handling not native to the . Interrupt 2Fh serves as a mechanism in , enabling the operating system and installed drivers to register sub-services for dynamic interception and redirection of calls, particularly for network integrations. For instance, Microsoft Networks and similar extensions use INT 2Fh to register sub-services that intercept DOS file I/O calls (via INT 21h) and redirect them to remote file servers, allowing transparent access to network resources as if they were local drives without altering core behavior. In its initial release, 1.0 (1981) depended entirely on interrupts for all hardware interactions, including keyboard input, video output, and storage operations, to ensure portability across varying PC configurations. By 5.0 (1991), however, direct hardware access had become prevalent among applications and even parts of the OS, bypassing for improved performance in areas like graphics and disk management, though backward compatibility preserved interrupt-based interfaces. Early Windows versions, such as Windows 3.x in 386 Enhanced mode, maintained compatibility with DOS and -dependent software by emulating the real-mode environment through Virtual 8086 (V86) mode, where interrupts are trapped and virtualized within sessions. This approach allowed multiple DOS applications to run concurrently while ensuring services, like video functions via , were safely executed in isolated virtual machines without compromising system stability.

Limitations and Modern Alternatives

Bypassing BIOS for Performance

In performance-critical applications under , developers frequently bypassed interrupt calls by programming I/O ports directly using assembly instructions like IN and OUT to access hardware registers. For video operations, this involved targeting specific ports such as 3C0h for the VGA attribute controller or 3C2h for the miscellaneous output register, enabling immediate control over display parameters without invoking the . This approach eliminated the latency of routine dispatching, parameter passing, and return handling, which could otherwise consume hundreds of CPU cycles per call. The slowness of BIOS services stemmed primarily from their reliance on polling loops to check hardware status flags, contrasting with (DMA) techniques that offload data transfers to dedicated controllers, freeing the CPU for other tasks. In real-mode environments like DOS, BIOS implementations in ROM were not optimized for high-speed operations, often incorporating unnecessary error checking and compatibility layers that exacerbated overhead; for instance, repetitive video updates via were significantly slower than direct writes to VGA memory at segment A000h due to these inefficiencies. Additionally, BIOS routines were inherently single-threaded and non-reentrant, posing challenges in nascent multitasking scenarios where concurrent access could lead to corruption or deadlocks. A prominent example of this bypassing technique appears in the 1993 game Doom, where id Software's engine directly accessed VGA hardware by writing pixels to the frame buffer at address 0xA0000 in 320x200x256 mode and manipulating ports for palette and mode switching, avoiding entirely to sustain playable frame rates on 386 and 486 processors. This direct method allowed efficient column rendering of walls and sprites, leveraging and lookup tables for speed without BIOS abstraction layers. However, such practices risked hardware incompatibility, as port assignments and register behaviors varied across VGA clones and cards, potentially causing display artifacts or crashes on non-IBM-compatible systems. As a partial alternative to full bypassing, the (VESA) introduced BIOS Extensions (VBE) in the early 1990s, extending with subfunctions (AH=4Fh) for standardized support, including mode queries, bank switching, and linear frame buffer access. VBE enabled developers to achieve near-direct performance—such as protected-mode transfers to video RAM—while maintaining portability across compliant hardware, with direct calls to window functions outperforming traditional dispatching for paging operations. Despite these improvements, high-performance applications like often still opted for vendor-specific direct access to maximize throughput in resource-constrained environments.

Transition to UEFI and Legacy Mode

The Unified Extensible Firmware Interface (), initially developed by as the Extensible Firmware Interface (EFI) with version 1.10 released in 2005, represents a significant evolution from the legacy architecture. UEFI establishes a standardized interface between operating systems and platform firmware, incorporating boot services for pre-OS initialization and runtime services that persist after the OS loads. Unlike , which depends on interrupt-based calls via the (IVT), UEFI employs a modular driver model with protocol-based interactions, eliminating the need for traditional software interrupts to access hardware services. This shift enables larger memory addressing, faster boot times, and support for modern features like Secure Boot, rendering interrupts obsolete in native UEFI environments. To maintain compatibility with older operating systems and bootloaders designed for BIOS, UEFI implementations include the Compatibility Support Module (CSM), a firmware component that emulates the legacy 16-bit real-mode environment. When enabled, CSM initializes the IVT at the traditional low-memory location (0x0000:0000) and hooks BIOS interrupt vectors, allowing INT calls—such as INT 10h for video services or INT 13h for disk I/O—to function as they would on pre-UEFI systems. This emulation layer translates legacy requests into UEFI protocols or direct hardware accesses, ensuring seamless operation for software unable to adapt to UEFI's native APIs. However, CSM operates at the expense of UEFI's full capabilities, including reduced security and performance overhead from mode switching between real mode and protected mode. The reliance on CSM has declined as modern operating systems prioritize native UEFI support, leading to its deprecation. Windows 11, released in 2021, mandates Secure Boot for compliance, which requires disabling CSM to enforce pure UEFI mode and prevent legacy code execution vulnerabilities; systems with CSM enabled fail Secure Boot validation and cannot install or upgrade to Windows 11 without reconfiguration. In the Linux ecosystem, kernel developers and distributions are actively phasing out legacy BIOS dependencies; for instance, Fedora has considered dropping BIOS boot support entirely, while SUSE evaluates removing it for future releases like SLE 16, citing the obsolescence of 16-bit interfaces and the need for enhanced security features. These changes reflect broader industry trends, with hardware vendors like Intel having largely eliminated CSM support since around 2020 for client platforms and by 2024 for servers to align with UEFI Class 3 certification. As of 2025, CSM support has been removed from most new Intel platforms, and distributions like SUSE are planning to drop legacy BIOS in upcoming releases such as SLE 16. A key example of this transition is disk access: in native UEFI without CSM, legacy INT 13h calls for block I/O operations result in errors or undefined behavior, as the BIOS interrupt is unsupported in 32-bit or 64-bit protected mode. Instead, UEFI provides the Block I/O Protocol, which offers equivalent read/write functionality with support for larger block sizes (up to 1 MB per transfer versus BIOS's 64 KB limit) and modern disk geometries like GUID Partition Tables (GPT). Applications or bootloaders attempting INT 13h without CSM must be recompiled or replaced with UEFI-aware equivalents to avoid failures during boot or runtime.

References

Add your contribution
Related Hubs
User Avatar
No comments yet.