| Address Range | Size | Type | Purpose |
|---|---|---|---|
| 0x00000 - 0x003FF | 1 KB | IVT | Interrupt Vector Table (256 vectors) |
| 0x00400 - 0x004FF | 256 B | BDA | BIOS Data Area (hardware config, EBDA pointer) |
| 0x00500 - 0x007FF | 768 B | Mixed | DOS/BIOS communication (often free pre-DOS) |
| 0x00800 - 0x07BFF | 30,208 B | Free | Conventional memory (stack, bootloader data) |
| 0x07C00 - 0x07DFF | 512 B | MBR | Boot sector (code + partition table) |
| 0x07E00 - 0x7FFFF | 491,520 B | Free | Conventional memory (stage 2, kernel, DOS) |
| 0x80000 - 0x9FFFF | 128 KB | Mixed | EBDA (if present) or free conventional memory |
| 0xA0000 - 0xBFFFF | 128 KB | VRAM | Video memory (graphics/text buffers) |
| 0xC0000 - 0xFFFFF | 256 KB | ROM | BIOS and option ROMs (read-only) |
| Address | Stack Space | Grows Into | Best For | Notes |
|---|---|---|---|---|
| 0x7BFF | ~30 KB | 0x00500 - 0x07BFF (free memory) | MBR/Stage 1 bootloaders | Just below MBR; simple and safe for minimal stack usage |
| 0x9000 | ~33 KB | 0x07E00 - 0x9000 (free memory) | Stage 2 bootloaders | More space; standard convention; check EBDA location first |
Verifying EBDA location (to ensure 0x9000 is safe):
MOV AX, [0x040E] ; Read EBDA segment from BDA (at 0x40E, not 0x408!)
SHL AX, 4 ; Convert to physical address
CMP AX, 0x9000 ; Is EBDA above 0x9000?
JA .safe ; Yes, 0x9000 is safe
; Otherwise use 0x7BFF or another location
.safe:
MOV SP, 0x9000| Address Range | Size | Purpose | Safety Notes |
|---|---|---|---|
| 0x00500 - 0x007FF | 768 B | Temp data, small buffers | Often free pre-DOS; safe for temporary storage |
| 0x00800 - 0x07BFF | 30,208 B | Stack (if SP=0x7BFF), temp data | Free conventional memory; ideal for stage 1 |
| 0x07C00 - 0x07DFF | 512 B | MBR code (loaded by BIOS) | Contains your bootloader; do not overwrite |
| 0x07E00 - 0x0FFFF | 33,280 B | Stage 2 bootloader, kernel loading | Directly after MBR; excellent for stage 2 code |
| 0x10000 - 0x7FFFF | 458,752 B | Kernel, large stage 2 bootloaders | Large free region; DOS programs load here |
| Address Range | Purpose | Why to Avoid |
|---|---|---|
| 0x00000 - 0x003FF | Interrupt Vector Table (IVT) | Critical for BIOS interrupts; corruption causes system failure |
| 0x00400 - 0x004FF | BIOS Data Area (BDA) | Contains BIOS variables; corruption breaks hardware access |
| 0xA0000 - 0xBFFFF | Video RAM (VRAM) | Memory-mapped I/O; writing here affects display, not general memory |
| 0xC0000 - 0xFFFFF | BIOS/Option ROMs | Read-only firmware; cannot be used for writable memory |
| Offset from 0x7C00 | Size | Purpose |
|---|---|---|
| 0x000 - 0x1BD | 446 bytes | Bootloader code |
| 0x1BE - 0x1CD | 16 bytes | Partition entry 1 |
| 0x1CE - 0x1DD | 16 bytes | Partition entry 2 |
| 0x1DE - 0x1ED | 16 bytes | Partition entry 3 |
| 0x1EE - 0x1FD | 16 bytes | Partition entry 4 |
| 0x1FE - 0x1FF | 2 bytes | Boot signature (0x55AA in little-endian) |
Stack (grows down from 0x7BFF or 0x9000)
[Free Memory]
Stage 2 Code/Data (0x07E00+)
[MBR Code] (0x7C00 - 0x7DFF)
[Free Memory] (0x00500 - 0x07BFF)
[BDA] (0x00400 - 0x004FF)
[IVT] (0x00000 - 0x003FF)
The IVT contains 256 interrupt vectors (4 bytes each: 2-byte offset + 2-byte segment).
| Address Range | Vector(s) | Purpose |
|---|---|---|
| 0x00000 - 0x00003 | INT 0x00 | Divide by zero exception |
| 0x00004 - 0x00007 | INT 0x01 | Single-step interrupt (debugging) |
| 0x00008 - 0x0000B | INT 0x02 | Non-maskable interrupt (NMI) |
| 0x0000C - 0x0000F | INT 0x03 | Breakpoint (INT 3) |
| 0x00010 - 0x00013 | INT 0x04 | Overflow (INTO instruction) |
| 0x00014 - 0x00017 | INT 0x05 | BOUND range exceeded / Print screen |
| 0x00018 - 0x0001B | INT 0x06 | Invalid opcode |
| 0x0001C - 0x0001F | INT 0x07 | Coprocessor not available |
| 0x00020 - 0x0003F | INT 0x08-0x0F | Hardware interrupts (PIC) |
| INT 0x08 | System timer (IRQ 0) | |
| INT 0x09 | Keyboard (IRQ 1) | |
| INT 0x0E | Floppy disk controller (IRQ 6) | |
| INT 0x0F | Parallel port (IRQ 7) | |
| 0x00040 - 0x0007F | INT 0x10-0x1F | BIOS services |
| INT 0x10 | Video services | |
| INT 0x11 | Equipment check | |
| INT 0x12 | Memory size | |
| INT 0x13 | Disk services | |
| INT 0x14 | Serial port services | |
| INT 0x15 | System services / Extended memory | |
| INT 0x16 | Keyboard services | |
| INT 0x17 | Printer services | |
| INT 0x18 | Boot failure / ROM BASIC | |
| INT 0x19 | Bootstrap loader | |
| INT 0x1A | Real-time clock / time services | |
| INT 0x1B | Ctrl+Break handler | |
| INT 0x1C | User timer tick | |
| INT 0x1D | Pointer to video parameter table | |
| INT 0x1E | Pointer to disk parameter table | |
| INT 0x1F | Pointer to graphics character table (8x8 font) | |
| 0x00080 - 0x000FF | INT 0x20-0x3F | DOS services (if DOS loaded) |
| INT 0x20 | Program terminate | |
| INT 0x21 | DOS services (file I/O, etc.) | |
| INT 0x22-0x2F | DOS internals and TSRs | |
| 0x00100 - 0x003FF | INT 0x40-0xFF | User interrupts / free (often unused or for applications) |
The BDA contains BIOS variables used during boot and runtime. Key entries:
| Address | Size | Purpose |
|---|---|---|
| 0x00400 - 0x00407 | 8 bytes | COM1-COM4 port addresses (2 bytes each: COM1 typically 0x3F8, COM2 0x2F8, etc.) |
| 0x00408 - 0x0040D | 6 bytes | LPT1-LPT3 printer port addresses (2 bytes each: LPT1 typically 0x378, etc.) |
| 0x0040E - 0x0040F | 2 bytes | EBDA segment address (extended BIOS data area base) ** CRITICAL for stack safety!** |
| 0x00410 - 0x00411 | 2 bytes | Equipment list (bit flags from INT 0x11: floppies, video, math coprocessor, etc.) |
| 0x00412 | 1 byte | Initialization flag / Manufacturing test |
| 0x00413 - 0x00414 | 2 bytes | Base memory size in KB (typically 640; from INT 0x12) |
| 0x00415 - 0x00416 | 2 bytes | Extended memory / Manufacturing scratch |
| 0x00417 | 1 byte | Keyboard shift flags byte 1 (Right Shift, Left Shift, Ctrl, Alt, Scroll Lock, Num Lock, Caps Lock, Insert) |
| 0x00418 | 1 byte | Keyboard shift flags byte 2 (Left Ctrl, Left Alt, SysRq pressed, Pause active, etc.) |
| 0x00419 | 1 byte | Alternate keypad entry storage |
| 0x0041A - 0x0041B | 2 bytes | Keyboard buffer head pointer (offset into buffer at 0x41E) |
| 0x0041C - 0x0041D | 2 bytes | Keyboard buffer tail pointer (offset into buffer at 0x41E) |
| 0x0041E - 0x0043D | 32 bytes | Keyboard buffer (16 entries × 2 bytes: scan code + ASCII; circular buffer) |
| 0x0043E | 1 byte | Floppy disk drive calibration status |
| 0x0043F | 1 byte | Floppy disk motor status |
| 0x00440 | 1 byte | Floppy disk motor timeout counter |
| 0x00441 | 1 byte | Floppy disk last operation status |
| 0x00442 - 0x00448 | 7 bytes | Floppy disk controller status bytes |
| 0x00449 | 1 byte | Current video mode |
| 0x0044A - 0x0044B | 2 bytes | Number of columns in text mode |
| 0x0044C - 0x0044D | 2 bytes | Video page size in bytes (regen buffer size) |
| 0x0044E - 0x0044F | 2 bytes | Current video page offset (start address) |
| 0x00450 - 0x0045F | 16 bytes | Cursor positions for 8 video pages (2 bytes per page: column, row) |
| 0x00460 - 0x00461 | 2 bytes | Cursor shape (start/end scan lines) |
| 0x00462 | 1 byte | Active video page number |
| 0x00463 - 0x00464 | 2 bytes | Video controller I/O port base (0x3D4 for CGA, 0x3B4 for MDA) |
| 0x00465 | 1 byte | Video mode register current setting |
| 0x00466 | 1 byte | CGA color palette |
| 0x00467 - 0x0046B | 5 bytes | Cassette data / POST work area |
| 0x0046C - 0x0046F | 4 bytes | Timer ticks since midnight (updated by INT 0x08, ~18.2065 Hz) |
| 0x00470 | 1 byte | Timer overflow flag (24-hour day rollover) |
| 0x00471 | 1 byte | Ctrl+Break flag |
| 0x00472 - 0x00473 | 2 bytes | POST reset flag (0x1234 = warm boot/skip memory test, 0x0000 = cold boot) |
| 0x00474 | 1 byte | Hard disk last operation status |
| 0x00475 | 1 byte | Number of hard disks detected |
| 0x00476 | 1 byte | Hard disk control byte |
| 0x00477 | 1 byte | Hard disk I/O port offset |
| 0x00478 - 0x0047B | 4 bytes | LPT1-LPT4 timeout counters (1 byte each) |
| 0x0047C - 0x0047F | 4 bytes | COM1-COM4 timeout counters (1 byte each) |
| 0x00480 - 0x00481 | 2 bytes | Keyboard buffer start offset (typically 0x001E) |
| 0x00482 - 0x00483 | 2 bytes | Keyboard buffer end offset (typically 0x003E) |
| 0x00484 | 1 byte | Video rows minus 1 (EGA/VGA: typically 24 for 25 rows) |
| 0x00485 - 0x00486 | 2 bytes | Character height in scan lines (VGA: 16 for 9x16 font) |
| 0x00487 | 1 byte | Video display data area (VGA mode control) |
| 0x00488 | 1 byte | Video display data area (VGA switches) |
| 0x00489 | 1 byte | Video display combination code |
| 0x0048A | 1 byte | Last diskette data rate selected |
| 0x0048B | 1 byte | Hard disk status register |
| 0x0048C | 1 byte | Hard disk error register |
| 0x0048D | 1 byte | Hard disk interrupt control flag |
| 0x0048E | 1 byte | Combination hard disk/floppy card control |
| 0x0048F - 0x00493 | 5 bytes | Floppy disk controller information |
| 0x00494 | 1 byte | Keyboard mode state and type flags |
| 0x00495 | 1 byte | Keyboard LED flags |
| 0x00496 - 0x00497 | 2 bytes | Offset to user wait flag pointer |
| 0x00498 - 0x0049B | 4 bytes | User wait timeout value |
| 0x0049C - 0x0049D | 2 bytes | RTC wait flag |
| 0x0049E - 0x004A7 | 10 bytes | Network adapter data area |
| 0x004A8 - 0x004FF | 88 bytes | Extended keyboard/video/miscellaneous BIOS data |
Key takeaway: Address 0x0040E (not 0x00408!) holds the EBDA segmentcritical for determining safe stack locations!
This area is used by DOS (if loaded) and some BIOS implementations:
| Address Range | Purpose |
|---|---|
| 0x00500 - 0x005FF | Print screen status, DOS kernel data (if DOS loaded) |
| 0x00600 - 0x007FF | Often free or used for temporary data by bootloaders |
Note: In many systems, 0x00500 - 0x007FF is effectively free during early boot (before DOS loads).
This is general-purpose free memory in most systems:
- Safe for bootloader stack, temporary data, or stage 2 code.
- 0x7BFF is at the top of this region, making it ideal for a stack base.
- Loaded by BIOS from the first sector of the boot device.
- Contains bootloader code + partition table + signature (0xAA55).
Layout:
| Offset | Size | Purpose |
|---|---|---|
| 0x000 - 0x1BD | 446 bytes | Bootloader code |
| 0x1BE - 0x1FD | 64 bytes | Partition table (4 entries × 16 bytes) |
| 0x1FE - 0x1FF | 2 bytes | Boot signature (0x55AA in little-endian) |
This is the largest free region in real mode:
| Subdivisions | Purpose |
|---|---|
| 0x07E00 - 0x0FFFF | Often used for stage 2 bootloader or kernel loading (33,280 bytes) |
| 0x10000 - 0x7FFFF | Conventional memory (DOS loads here; OS kernels often loaded here) (458,752 bytes) |
Key points:
- 0x9000 is in this regionsafe for a larger stack.
- DOS traditionally uses 0x10000 - 0x9FFFF for programs.
This region's usage varies by BIOS:
| Scenario | Address Range | Purpose |
|---|---|---|
| EBDA present | 0x9FC00 - 0x9FFFF (typical 1 KB) | Extended BIOS data (typically 1-18 KB; varies by system) |
| No EBDA | 0x80000 - 0x9FFFF | Free conventional memory (rare on post-1980s systems) |
How to detect EBDA:
MOV AX, [0x040E] ; Read EBDA segment from BDA (correct offset!)
SHL AX, 4 ; Convert to physical address (AX = EBDA base)Typical EBDA contents:
- Additional BIOS variables (e.g., ACPI tables, disk parameters).
- PnP BIOS structures.
- Runtime data for BIOS interrupts.
- On PS/2 systems, EBDA is always present (typically 1 KB starting at 0x9FC00).
This region is reserved for video hardware:
| Address Range | Mode | Purpose |
|---|---|---|
| 0xA0000 - 0xAFFFF | EGA/VGA graphics | 64 KB graphics buffer (planar modes) |
| 0xB0000 - 0xB7FFF | Monochrome text | 32 KB text buffer (MDA, Hercules) |
| 0xB8000 - 0xBFFFF | Color text | 32 KB text buffer (CGA, VGA text mode) |
Example: In 80×25 text mode, 0xB8000 is the start of the screen buffer (2 bytes per character: ASCII + attribute).
** Do NOT use for stack or general memory!**
This region contains read-only firmware:
| Address Range | Purpose |
|---|---|
| 0xC0000 - 0xC7FFF | VGA BIOS ROM (32 KB typical) |
| 0xC8000 - 0xEFFFF | Other option ROMs (network cards, SCSI controllers, etc.) |
| 0xF0000 - 0xFFFFF | System BIOS ROM (64 KB) |
| 0xFFFF0 - 0xFFFFF | BIOS entry point (16 bytes, includes reset vector at 0xFFFF0) |
Reset vector (at power-on):
- CPU starts at CS:IP = 0xF000:0xFFF0 (physical 0xFFFF0).
- First instruction is typically a far jump to the main BIOS code.
- This cheat sheet applies to legacy BIOS systems (IBM PC/AT standard), not UEFI. UEFI uses completely different boot mechanisms (GPT, ESP, .efi executables).
- BDA offsets are IBM PC/AT standard; minor variants exist in clones (e.g., PS/2 systems always have EBDA present). Use tools like DEBUG.COM to inspect actual BDA contents on target hardware.
- Memory layout can vary slightly between BIOS implementationsalways test on target hardware or emulators (QEMU, Bochs, VirtualBox).
- Always verify EBDA location before using addresses near 0x9FFFF (use the code snippet provided).
- Stack grows downward (toward lower addresses) in x86 architecture.
- For extended memory detection (>1 MB), use INT 0x15, EAX=0xE820 (E820 memory map) in protected mode or during boot.
- For hybrid boot setups (legacy + UEFI), consider integration with modern bootloaders like GRUB2 or systemd-boot.
Accuracy: This corrected edition fixes critical errors in the BDA layout (especially EBDA pointer location) and provides precise byte counts for memory regions. Based on IBM PC Technical Reference and OSDev Wiki documentation.