明天开始学习闪客老师的《Linux源码趣读》
在开机的时侯,显卡上的BIOS程序会把硬碟启动区的512个字节复制到显存里的0x7c00的位置,再跳转到这儿运行。
开机后初始化指向BIOS
CPU中的PC寄存器,储存着即即将执行的指令的显存地址。开机时须要初始化PC寄存器的值为0xFFFF0。这是Intel指南龟腚的,硬件厂商只是实现而已。(这地位觉得和码农也没哪些差异)
CPU的地址线除了联接显存(RAM)linux培训班,还有ROM(BIOS),还有一些额外的IO端口。这儿的初始值0xFFFF0就是BIOS所在的ROM区。
硬碟启动区
先来了解一下启动区
怎样确定启动区?
硬碟中的0盘0道1磁道(第一磁道)的512个字节的最后2个字节分别是0x55和0xaa,BIOS都会觉得它是启动区。
放在第一磁道
Linux-0.11从bootsect.s开始,
经过编译后,bootsect.s会被编译成二补码文件linux磁盘写满启动,置于启动区的第一磁道。
加载到显存
后面说了BIOS会把代码复制到0x7c00的位置,具体如何复制的还是得看bootsect.s里的代码:
.equ BOOTSEG, 0x07c0 # original address of boot-sector
……
ljmp $BOOTSEG, $_start
_start:
mov $BOOTSEG, %ax #将ds段寄存器设置为0x7C0
mov %ax, %ds
这儿是汇编撰的,
先把BOOTSEG常量搞成0x07c0。再把BOOTSEG的值给到寄存器ax。再把寄存器ax里的值给到段寄存器ds。
好了,经过那么一忙活,如今ds里就是0x07c0了。段寄存器主要是拿来显存轮询用的。
段基址(左移4位)+偏斜量=真正的显存地址。
(王爽老师的《汇编语言》讲的比较清楚,感兴趣的话,我们拆那本书的时侯再详尽说)
代码里的0x07c0就是由于左移了4位才弄成0x7c00的。
小结
开机时,BIOS程序将系统代码复制到0x7c00处;通过bootsect.s的几行代码,更改了段寄存器的值为0x07c0。
这儿32位64位都是加载到0x7c00处,这儿CPU还处于16位的实模式下linux,还得兼容老祖宗的位置。看来CPU的发展也有历史包袱。
至于为何是0x7c00可以参考阮一峰大鳄的这篇文章:
假如你感觉有点收获,欢迎点个关注linux磁盘写满启动,也欢迎分享给你身边的同事。
#头条创作挑战赛##程序员#