编程技术分享平台

网站首页 > 技术教程 正文

Linux源码学习笔记 day1 开机时如何加载系统?

xnh888 2025-06-12 18:30:14 技术教程 3 ℃ 0 评论

今天开始学习 闪客老师的《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

这里是汇编写的,

  1. 先把 BOOTSEG 常量搞成 0x07c0 。
  2. 再把 BOOTSEG的值给到 寄存器ax。
  3. 再把 寄存器ax 里的值给到 段寄存器ds。

好了,经过这么一倒腾,现在ds里就是0x07c0了。段寄存器 主要是用来内存寻址用的。

段基址(左移4位) + 偏移量 = 真正的内存地址。

(王爽老师的《汇编语言》讲的比较清楚,感兴趣的话,我们拆那本书的时候再详细说)

代码里的0x07c0 就是因为左移了4位才变成0x7c00的。

小结

  1. 开机时,BIOS程序将系统代码复制到0x7c00处;
  2. 通过bootsect.s 的几行代码,修改了段寄存器的值为0x07c0。

这里32位 64位都是 加载到 0x7c00处,这里CPU还处于16位的实模式下,还得兼容老祖宗的位置。看来CPU的发展也有历史包袱。

至于为什么是0x7c00 可以参考阮一峰大佬的这篇文章:
http://www.ruanyifeng.com/blog/2015/09/0x7c00.html

如果你觉得有点收获,欢迎点个关注, 也欢迎分享给你身边的朋友。


#头条创作挑战赛##程序员#

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表