从按下开机键开始的计算机启动过程:
(主要包括 从主板加载BIOS并执行、从磁盘加载启动区并执行、从磁盘加载操作系统并执行 三步,是依次递进的,详情参阅 全网最硬核详解计算机启动过程-公众号低并发编程)
加载BIOS:按下开机键,主板ROM的BIOS被(被谁?)加载到到内存 0xffff0 处,CPU 将 PC 寄存器的值强制初始化为 0xffff0(一跳)。
执行BIOS代码:
阶段1(0xffff0 处的内容):该入口地址处存的是一个跳转指令,跳转的目的地是内存 0xfe05b 位置,该位置存了BIOS的真正内容。执行该跳转(二跳)。
阶段2(0xfe05b 处的内容):执行硬件检测、硬件初始化、建立中断向量表等工作后,找到磁盘上的启动区(或称引导区)加载到内存 0x7c00 位置,并跳转到该位置(三跳)。
执行启动区代码(0x7c00 处的内容):从磁盘加载OS内核到内存,与上面不同这里内存位置不是固定的了,并跳转到OS内核代码处(四跳)。
执行OS内核代码:包括开启分段机制、进入保护模式、开启中断机制等,执行完后系统由OS接手管理。具体过程见下文“操作系统启动过程”部分。
整体过程概要:
补充:
BIOS位于主板ROM,启动时被加载到内存;启动区、OS位于磁盘,被先后加载到内存。BIOS、启动区在内存的位置是固定的(为啥是这三个值?早期定死的);而OS在内存位置不是固定的。
启动区:若一个磁盘上0盘0道1扇区的内容(512B)的末两个字节为0x55、0xaa,则这该扇区会被BIOS识别为启动区,该磁盘会被当做可启动盘。往一个磁盘烧录OS后之所以可以当做启动盘就是因为往该位置写入了这些特殊数据。若装了多系统,则启动时会列出并让用户选择要启动的系统,这些系统就是根据上述条件被识别得到。
可见,一个程序只要其虚拟内存以0x7c00作为段地址,且按上述条件烧录到磁盘,则就可以被BIOS识别为启动区加载到内存执行。因此,如果该程序逻辑中不是去加载OS而是直接输出数据,则该程序自身就是一个简洁的"操作系统"。示例(更多详情可参阅 自制操作简易系统-公众号低并发编程):
;将此段程序烧录成硬盘启动区即可作为一个“操作系统“ ;BIOS把启动区加载到内存的该位置 ;所以需设置地址偏移量 section mbr vstart=0x7c00 ;直接往显存中写数据 mov ax,0xb800 ;这条就是第一条指令 mov gs,ax mov byte [gs:0x00],'h' mov byte [gs:0x02],'e' mov byte [gs:0x04],'l' mov byte [gs:0x06],'l' mov byte [gs:0x08],'o' mov byte [gs:0x0a],' ' mov byte [gs:0x0c],'w' mov byte [gs:0x0e],'o' mov byte [gs:0x10],'r' mov byte [gs:0x12],'l' mov byte [gs:0x14],'d' jmp $ ;512字节的最后两字节是启动区标识 times 510-($-$$) db 0 db 0x55,0xaa