The x86 Real Mode Memory Map is as follows:
- 0x00000000 - 0x000003FF - Real Mode Interrupt Vector Table
- 0x00000400 - 0x000004FF - BIOS Data Area
- 0x00000500 - 0x00007BFF - Unused
- 0x00007C00 - 0x00007DFF - Our Bootloader
- 0x00007E00 - 0x0009FFFF - Unused
- 0x000A0000 - 0x000BFFFF - Video RAM (VRAM) Memory
- 0x000B0000 - 0x000B7777 - Monochrome Video Memory
- 0x000B8000 - 0x000BFFFF - Color Video Memory
- 0x000C0000 - 0x000C7FFF - Video ROM BIOS
- 0x000C8000 - 0x000EFFFF - BIOS Shadow Area
- 0x000F0000 - 0x000FFFFF - System BIOS
In my real mode programming I usually stick from 0x00007E00 - 0x0009FFFF (Not all of it).. I use segment:offset addressing to use the memory.. To go from a 1 Stage bootloader to a Kernel or a Bootloader 2nd Stage, I use:
; bootloader.s
BITS 16
ORG 0x7C00
CLI
JMP 0xE000 ; Can also be JMP 0x7C00:200
HLT
TIMES 510 - ($-$$) DB 0
DW 0xAA55
--
; Something.s
BITS 16
ORG 0x7E00 ; Can also be ORG 0x7C00:200
; Code goes here for your purposes.. whether it be a 2nd stage
; bootloader or your 16bit kernel..
CLI
HLT
If you are going into Protected mode, you will still need a stub as shown above.. In Something.s you can program in your protected mode routines (GDT, A20, Set video mode, etc..)
To explain about the memory location at 0x7C00 (Bootloader Entry Point), 0x7C00 - 0x7DFF is where you place your bootloader (the bootloader.s above). You place it there because the BIOS jumps to that location after doing its routines. The bootloader must be exactly 512 bytes in size (notice the TIMES directive). From there, your code can be any size (as long as it fits in the memory map), and you will be able to work on the OS fully.
If you DO go into 32Bit Protected Mode, you will be able to use ANYTHING about the 1MiB mark.
From the linked article:
In practice, the MBR usually contains a boot loader whose purpose is to load another boot loader - to be found at the start of one of the partitions. This is often a very simple program which finds the first partition marked Active, loads its first sector into RAM, and commences its execution. Since by convention the new boot loader is also loaded to adress 7C00h, the old loader may need to relocate all or part of itself to a different location before doing this. Also, ES:SI is expected to contain the address in RAM of the partition table, and DL the boot drive number. Breaking such conventions may render a bootloader incompatible with other bootloaders.
Best Answer
from the OS dev Wiki, which is where I get information when I'm playing with my toy OS's