Intel 80x86 series CPUs can run in 16 bit real mode and 32-bit protected mode respectively. In order to be compatible and solve the initial startup problem, Intel designed the hardware of all 80x86 series CPUs, including the latest model CPUs, to run in 16 bit real mode when powered on.
The CPU hardware logic is designed to forcibly set the value of CS to 0xF000 and the value of IP to 0xFFF0 at the moment of power on, so that CS:IP points to 0xFFFF0 (BIOS address range).
The BIOS program builds the interrupt vector table with 1KB memory space (0x00000~0x003FF) at the beginning of the memory (0x00000), builds the BIOS data area (0x00400~0x004FF) with 256 bytes space next to it, and loads several interrupt service programs corresponding to the interrupt vector table of about 8KB at the position after about 57KB (0x0E05B).
256 interrupt vectors, each occupying 4KB (CS,IP)
After the BIOS executes a series of BIOS codes, the computer completes self-test and other operations. Then it falls into INT 19 interrupt.
INT 19 is to load the program (512B) in the first sector of the floppy disk to the specified location (0x07C00) in the memory.
! ! SYS_SIZE is the number of clicks (16 bytes) to be loaded. ! 0x3000 is 0x30000 bytes = 196kB, more than enough for current ! versions of linux ! SYSSIZE = 0x3000 ! ! bootsect.s (C) 1991 Linus Torvalds ! ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves ! iself out of the way to address 0x90000, and jumps there. ! ! It then loads 'setup' directly after itself (0x90200), and the system ! at 0x10000, using BIOS interrupts. ! ! NOTE! currently system is at most 8*65536 bytes long. This should be no ! problem, even in the future. I want to keep it simple. This 512 kB ! kernel size should be enough, especially as this doesn't contain the ! buffer cache as in minix ! ! The loader has been made as simple as possible, and continuos ! read errors will result in a unbreakable loop. Reboot by hand. It ! loads pretty fast by getting whole sectors at a time whenever possible. .globl begtext, begdata, begbss, endtext, enddata, endbss .text begtext: .data begdata: .bss begbss: .text SETUPLEN = 4 ! nr of setup-sectors BOOTSEG = 0x07c0 ! original address of boot-sector INITSEG = 0x9000 ! we move boot here - out of the way SETUPSEG = 0x9020 ! setup starts here SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). ENDSEG = SYSSEG + SYSSIZE ! where to stop loading ! ROOT_DEV: 0x000 - same type of floppy as boot. ! 0x301 - first partition on first drive etc ROOT_DEV = 0x306
SYSSIZE is the linux system size that BIOS needs to load, 0x3000 * 16B = 196KB
In the first part, copy the bootstart program itself (all 512B contents) from memory 0x07C00 (BOOTSEG) to 0x90000 (INITSEG):
entry start start: mov ax,#BOOTSEG mov ds,ax mov ax,#INITSEG mov es,ax mov cx,#256 sub si,si sub di,di rep movw
Copy cx "words" (2 bytes) from DS:SI to ES:DI
After copying, jump to 0x9000:[go]:
The JMPI instruction: Set CS: IP = 0x9000: [go]
Set related registers:
go: mov ax,cs mov ds,ax mov es,ax ! put stack at 0x9ff00. mov ss,ax mov sp,#0xFF00 ! arbitrary value >>512
Set DS and es to 0x9000
And set the stack top as SS:SP = 0x9FF00
Use INT 13 interrupt to load the setup program (4 sectors) to 0x90200 (close to bootect):
load_setup: mov dx,#0x0000 ! drive 0, head 0 mov cx,#0x0002 ! sector 2, track 0 mov bx,#0x0200 ! address = 512, in INITSEG mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors int 0x13 ! read it jnc ok_load_setup ! ok - continue
Number of AL read sectors
CH cylinder [0, 79]
CL sector [1, 18]
DH head [0, 1]
DL drive (0x0~0x7F floppy disk, 0x80~0xFF hard disk)
ES:BX load address
CF=0 success, AH=0 at this time
CF=1 failed, AH = status code
After that, some parameters are obtained through INT 13 (AH=8), some characters are printed by INT 10, and then the system of 240 sectors is loaded to 120KB space after 0x10000 through INT 13 (the remaining bootect code is not read in detail)
Then determine a root device number
Jump to 0x90200:
That is, setup.s