# 操作系统实战45讲

## 程序的运行过程：从代码到机器运行

程序编译过程：

我们使用gcc来完成对c文件的编译，主要指令为：`gcc helloworld.c -o Helloworld`

gcc仅仅只是编译工作的驱动程序，具体的执行流程如下：

HelloWorld.c ——gcc预处理器——> HelloWorld.i ——gcc编译器——> HelloWorld.s ——gcc汇编器——> HelloWorld.o ——gcc链接器——> 可执行文件

![img](https://static001.geekbang.org/resource/image/f2/4a/f2b10135ed52436888a793327e4d5a4a.jpg)

存在的主要步骤为：

* 预处理：加入头文件，替换宏，输出.i文件

指令：`gcc -E helloworld.c -o helloworld.i`：-E预处理完成停止

* 编译：将C程序转换为汇编程序，输出.s文件

指令：`gcc -S helloworld.c -o helloworld.s`：-S编译完成停止

* 汇编：将汇编程序转换为可链接的二进制程序，输出.o文件

指令：`gcc -C helloworld.c -o helloworld.o`：-C汇编完成停止

* 链接：将可链接的二进制文件和其他别的库链接在一起，形成可执行的程序文件，输出可执行文件

最常规的一步到位的了：`gcc helloworld.c -o helloworld`

都可以从中间文件来进行gcc

![image-20211013233716108](https://gitee.com/LuckyCurve/img/raw/master/img/image-20211013233716108.png)

程序装载与执行

依赖冯诺依曼体系架构的五大设备：

* 装载数据和程序的输入设备
* 显示处理结果的输出设备
* 完成数据加工处理的运算器
* 控制程序执行的控制器
* 记录程序和数据的存储器

前两者主要是用来交互，后三者共同构成主体

![img](https://static001.geekbang.org/resource/image/bd/26/bde34df011c397yy42dc00fe6bd35226.jpg)

运算器和控制器一起封装成控制处理单元，控制处理单元通过总线与外部打交道

地址总线完成寻址，数据总线完成数据交换，控制总线完成对整个动作的控制

回到程序装载，使用`objdump -d helloworld`执行反汇编操作，得到以下汇编代码

![img](https://static001.geekbang.org/resource/image/39/14/3991a042107b90612122b14596c65614.jpeg)

信息表示：

第一列：地址

第二列：真正装入机器的代码数据

第三列：对应的汇编代码

第四列：代码相关注释

数据装载完成之后的图例为：

![img](https://static001.geekbang.org/resource/image/5d/6e/5d4889e7bf20e670ee71cc9b6285c96e.jpg)

## 实现一个最简单的内核

类似操作系统的HelloWorld，当然需要使用汇编和C

现有的商业操作系统都是基于这两种语言写出来的，操作系统开机的引导流程如下（如我们需要启动的操作系统是Hello OS）

![img](https://static001.geekbang.org/resource/image/f2/bd/f2d31ab7144bf309761711efa9d6d4bd.jpg)

之所以要使用汇编语言是因为C语言是无法直接操作特定的硬件的，而C当中的函数调用又依赖于栈结构，因此需要汇编来完成一些初始化操作

剩下直接就是实操了，参考文章https://blog.csdn.net/chenchengwudi/article/details/116707122
