【从头到脚品读 Linux 0.11 源码】第一回 最开始的两行代码
从这一篇开始,您就将跟着我一起进入这操作系统的梦幻之旅!
别担心,每一章的内容会非常的少,而且你也不要抱着很大的负担去学习,只需要像读小说一样,跟着我一章一章读下去就好。
话不多说,直奔主题。当你按下开机键的那一刻,在主板上提前写死的固件程序 BIOS 会将硬盘中启动区的 512 字节的数据,原封不动复制到内存中的 0x7c00 这个位置,并跳转到那个位置进行执行。

启动区的定义非常简单,只要硬盘中的 0 盘 0 道 1 扇区的 512 个字节的最后两个字节分别是 0x55 和 0xaa,那么 BIOS 就会认为它是个启动区。
所以对于我们理解操作系统而言,此时的 BIOS 仅仅就是个代码搬运工,把 512 字节的二进制数据从硬盘搬运到了内存中而已。所以作为操作系统的开发人员,仅仅需要把操作系统最开始的那段代码,编译并存储在硬盘的 0 盘 0 道 1 扇区即可。之后 BIOS 会帮我们把它放到内存里,并且跳过去执行。
而 Linux-0.11 的最开始的代码,就是这个用汇编语言写的 bootsect.s,位于 boot 文件夹下。

通过编译,这个 bootsect.s 会被编译成二进制文件,存放在启动区的第一扇区。

随后就会如刚刚所说,由 BIOS 搬运到内存的 0x7c00 这个位置,而 CPU 也会从这个位置开始,不断往后一条一条语句无脑地执行下去。
那我们的梦幻之旅,就从这个文件的第一行代码开始啦!
mov ax,0x07c0
mov ds,ax
好吧,先连续看两行。
这段代码是用汇编语言写的,含义是把 0x07c0 这个值复制到 ax 寄存器里,再将 ax 寄存器里的值复制到 ds 寄存器里。那其实这一番折腾的结果就是,让 ds 这个寄存器里的值变成了 0x07c0。

ds 是一个 16 位的段寄存器,具体表示数据段寄存器,在内存寻址时充当段基址的作用。啥意思呢?就是当我们之后用汇编语言写一个内存地址时,实际上仅仅是写了偏移地址,比如:
mov ax, [0x0001]
实际上相当于
mov ax, [ds:0x0001]
ds 是默认加上的,表示在 ds 这个段基址处,往后再偏移 0x0001 单位,将这个位置的内存数据,复制到 ax 寄存器中。
形象地比喻一下就是,你和朋友商量去哪玩比较好,你说天安门、南锣鼓巷、颐和园等等,实际上都是偏移地址,省略了北京市这个基址。
当然你完全可以说北京天安门、北京南锣鼓巷这样,每次都加上北京这个前缀。不过如果你事先和朋友说好,以下我说的地方都是北京市里的哈,之后你就不用每次都带着北京市这个词了,是不是很方便?
那 ds 这个数据段寄存器的作用就是如此,方便了描述一个内存地址时,可以省略一个基址,没什么神奇之处。
ds : 0x0001
北京市 : 南锣鼓巷
再看,这个 ds 被赋值为了 0x07c0,由于 x86 为了让自己在 16 位这个实模式下能访问到 20 位的地址线这个历史因素(不了解这个的就先别纠结为啥了),所以段基址要先左移四位。那 0x07c0 左移四位就是 0x7c00,那这就刚好和这段代码被 BIOS 加载到的内存地址 0x7c00 一样了。
也就是说,之后再写的代码,里面访问的数据的内存地址,都先默认加上 0x7c00,再去内存中寻址。
为啥统一加上 0x7c00 这个数呢?这很好解释,BIOS 规定死了把操作系统代码加载到内存 0x7c00,那么里面的各种数据自然就全都被偏移了这么多,所以把数据段寄存器 ds 设置为这个值,方便了以后通过这种基址的方式访问内存里的数据。

OK,赶紧消化掉前面的知识,那本篇就到此为止,只讲了两行代码,知识量很少,我没骗你吧。
希望你能做到,对 BIOS 将操作系统代码加载到内存 0x7c00,以及我们通过 mov 指令将默认的数据段寄存器 ds 寄存器的值改为 0x07c0 方便以后的基址寻址方式,这两件事在心里认可,并且没有疑惑,这才方便后面继续进行。
后面的世界越来越精彩,欲知后事如何,且听下回分解。
------- 本回扩展资料 -------
有关寄存器的详细信息,可以参考 Intel 手册:
Volume 1 Chapter 3.2 OVERVIEW OF THE BASIC EXECUTION ENVIRONMEN
有关计算机启动部分的原理如果还不清楚,可以看我之前的一篇文章了解一下:
如果想了解计算机启动时详细的初始化过程,还是得参考 Intel 手册:
Volume 3A Chapter 9 PROCESSOR MANAGEMENT AND INITIALIZATION
------- 关于本系列 -------
本系列的开篇词看这
本系列的扩展资料看这,这里有很多有趣的资料、答疑、互动参与项目,持续更新中,希望有你的参与。
https://github.com/sunym1993/flash-linux0.11-talk
本系列全局视角

最后,祝大家都能追更到系列结束,只要你敢持续追更,并且把每一回的内容搞懂,我就敢让你在系列结束后说一句,我对 Linux 0.11 很熟悉。
另外,本系列完全免费,希望大家能多多传播给同样喜欢的人,同时给我的 GitHub 项目点个 star,这些就足够让我坚持写下去了!我们下回见。
【从头到脚品读 Linux 0.11 源码】第一回 最开始的两行代码的更多相关文章
- Linux 0.11源码阅读笔记-文件管理
Linux 0.11源码阅读笔记-文件管理 文件系统 生磁盘 未安装文件系统的磁盘称之为生磁盘,生磁盘也可以作为文件读写,linux中一切皆文件. 磁盘分区 生磁盘可以被分区,分区中可以安装文件系统, ...
- Linux 0.11源码阅读笔记-中断过程
Linux 0.11源码阅读笔记-中断过程 是什么中断 中断发生时,计算机会停止当前运行的程序,转而执行中断处理程序,然后再返回原被中断的程序继续运行.中断包括硬件中断和软件中断,硬中断是由外设自动产 ...
- Linux 0.11源码阅读笔记-总览
Linux 0.11源码阅读笔记-总览 阅读源码的目的 加深对Linux操作系统的了解,了解Linux操作系统基本架构,熟悉进程管理.内存管理等主要模块知识. 通过阅读教复杂的代码,锻炼自己复杂项目代 ...
- Linux 0.11源码阅读笔记-总结
总结 Linux 0.11主要包含文件管理和进程管理两个部分.进程管理包括内存管理.进程管理.进程间通信模块.文件管理包含磁盘文件系统,打开文件内存数据.磁盘文件系统包括空闲磁盘块管理,文件数据块的管 ...
- Linux 0.11源码阅读笔记-块设备驱动程序
块设备驱动程序 块设备驱动程序负责实现对块设备数据的读写功能.内核代码统一使用缓冲块间接和块设备(如磁盘)交换数据,缓冲区数据通过块设备驱动程序和块设备交换数据. 块设备的管理 块设备表 内核通过一张 ...
- Linux 0.11源码阅读笔记-文件IO流程
文件IO流程 用户进程read.write在高速缓冲块上读写数据,高速缓冲块和块设备交换数据. 什么时机将磁盘块数据读到缓冲块? 什么时机将缓冲块数据刷到磁盘块? 函数调用关系 read/write( ...
- Linux 0.11源码阅读笔记-内存管理
内存管理 Linux内核使用段页式内存管理方式. 内存池 物理页:物理空闲内存被划分为固定大小(4k)的页 内存池:所有空闲物理页组成内存池,以页为单位进行分配回收.并通过位图记录了每个物理页是否空闲 ...
- linux 0.11 源码学习+ IO模型
http://www.cnblogs.com/Fredric-2013/category/696688.html
- Linux 0.11源码阅读笔记-高速缓冲
高速缓冲 概念 高速缓冲区是内存中的一块内存,在块设备与内核其它程序之间起着一个桥梁作用.内核程序如果需要访问块设备中的数据,都需要经过高速缓冲区来间接的操作. 高速缓冲区结构 高速缓冲区被划分为1k ...
随机推荐
- 高德 Serverless 平台建设及实践
作者 | 邓学祥(祥翼) 来源 | Serverless 公众号 高德从 FY21 财年开始启动 Serverless 建设,至今一年了,高德 Serverless 业务的峰值超过十万 qps 量级, ...
- 高级爬虫面试题测试题 v1.3
Python Web高级爬虫工程师测试题 (请本文件发送到: SpiderTestQuestion@163.com 并附带简历) 1. 用yield写一个斐波那契数列的生成器函数. 2. 放一段scr ...
- NOI 2021 部分题目题解
最近几天复盘了一下NOI 2021,愈发发觉自己的愚蠢,可惜D2T3仍是不会,于是只写前面的题解 Day1 T1 可以发现,每次相当于将 \(x\to y\) 染上一种全新颜色,然后一条边是重边当且仅 ...
- 题解 CF961G 【Partitions】
题目传送门 题目大意 给出\(n,k\),以及\(w_{1,2,..,n}\),定义一个集合\(S\)的权值\(W(S)=|S|\sum_{x\in S} w_x\),定义一个划分\(R\)的权值为\ ...
- MyBatis概念和”安装“
MyBatis概念 MyBatis的前身就是iBatis,本是apache的一个开源项目,2010年这个项目由apahce sofeware foundation 迁移到了google code,并且 ...
- nginx搭建网站踩坑经历
为了更好的阅读体验,请访问我的个人博客 前言 早上刷抖音刷到一个只需要三步的nginx搭建教程(视频地址),觉得有些离谱,跟着复现了一遍,果然很多地方不严谨并且省略了大量步骤,对于很多不了解linux ...
- Django Model字段加密的优雅实现
早前的一篇文章Django开发密码管理表实例有写我们写了个密码管理工具来实现对密码的管理,当时加密解密的功能在view层实现,一直运行稳定所以也没有过多关注实现是否优雅的问题.最近要多加几个密码表再次 ...
- 【UE4 C++】简单获取名称、状态、时间、帧数、路径与FPaths
基于UKismetSystemLibrary 获取各类名称 // Returns the actual object name. UFUNCTION(BlueprintPure, Category = ...
- Shiro反序列化的检测与利用
1. 前言 Shiro 是 Apache 旗下的一个用于权限管理的开源框架,提供开箱即用的身份验证.授权.密码套件和会话管理等功能. 2. 环境搭建 环境搭建vulhub 3. 如何发现 第一种情况 ...
- 从浏览器发送请求给SpringBoot后端时,是如何准确找到哪个接口的?(下篇)
纸上得来终觉浅,绝知此事要躬行 注意: 本文 SpringBoot 版本为 2.5.2; JDK 版本 为 jdk 11. 前言: 前文:你了解SpringBoot启动时API相关信息是用什么数据结构 ...