今天开始学习 闪客老师的《Linux源码趣读》
在开机的时候,主板上的 BIOS程序 会把硬盘启动区的512个字节复制到内存里的0x7c00的位置,再跳转到这里运行。
开机后初始化 指向BIOS
CPU中的PC寄存器,存储着即将要执行的指令的内存地址。开机时需要初始化PC寄存器的值为0xFFFF0。这是Intel手册龟腚的,硬件厂商只是实现而已。(这地位感觉和码农也没什么差别)
CPU的地址线不仅连接内存(RAM),还有ROM(BIOS),还有一些额外的IO端口。这里的初始值0xFFFF0 就是 BIOS所在的ROM区。
先来了解一下启动区
硬盘中的0盘0道1扇区(第一扇区)的512个字节的最后2个字节分别是0x55和0xaa,BIOS就会认为它是启动区。
Linux-0.11 从bootsect.s开始,
经过编译后,bootsect.s 会被编译成二进制文件,放在启动区的第一扇区。
前面说了BIOS会把代码复制到0x7c00的位置,具体怎么复制的还是得看bootsect.s里的代码:
.equ BOOTSEG, 0x07c0 # original address of boot-sector
……
ljmp $BOOTSEG, $_start
_start:
mov $BOOTSEG, %ax #将ds段寄存器设置为0x7C0
mov %ax, %ds
这里是汇编写的,
好了,经过这么一倒腾,现在ds里就是0x07c0了。段寄存器 主要是用来内存寻址用的。
段基址(左移4位) + 偏移量 = 真正的内存地址。
(王爽老师的《汇编语言》讲的比较清楚,感兴趣的话,我们拆那本书的时候再详细说)
代码里的0x07c0 就是因为左移了4位才变成0x7c00的。
小结
这里32位 64位都是 加载到 0x7c00处,这里CPU还处于16位的实模式下,还得兼容老祖宗的位置。看来CPU的发展也有历史包袱。
至于为什么是0x7c00 可以参考阮一峰大佬的这篇文章:http://www.ruanyifeng.com/blog/2015/09/0x7c00.html