(2021年11月3日打卡第六天)
打卡第六天:01 | 程序的运行过程:从代码到机器运行
你知道程序是如何运行的吗?
因此今天,作者将带领你从“Hello World”起,扎实基本功,探索程序如何运行的所有细节和原理。
#include "stdio.h"
int main(int argc, char const *argv[])
{
printf("Hello World!\n");
return 0;
}
计算机硬件是无法直接运行这个 C 语言文本程序代码的,需要 C 语言编译器,把这个代码编译成具体硬件平台的二进制代码。再由具体操作系统建立进程,把这个二进制文件装进其进程的内存空间中,才能运行。
1、程序编译过程
使用命令:gcc HelloWorld.c -o HelloWorld 或者 gcc ./HelloWorld.c -o ./HelloWorld ,就可以编译这段代码。其实,GCC 只是完成编译工作的驱动程序,它会根据编译流程分别调用预处理程序、编译程序、汇编程序、链接程序来完成具体工作。
下图就是编译这段代码的过程:

其实,我们也可以手动控制以上这个编译流程,从而留下中间文件方便研究:
- gcc HelloWorld.c -E -o HelloWorld.i 预处理:加入头文件,替换宏。
- gcc HelloWorld.c -S -c -o HelloWorld.s 编译:包含预处理,将 C 程序转换成汇编程序。
- gcc HelloWorld.c -c -o HelloWorld.o 汇编:包含预处理和编译,将汇编程序转换成可链接的二进制程序。
- gcc HelloWorld.c -o HelloWorld 链接:包含以上所有操作,将可链接的二进制程序和其它别的库链接在一起,形成可执行的程序文件。
2、程序装载执行
根据冯诺依曼体系结构构成的计算机,必须具有如下功能:
- 把程序和数据装入到计算机中;
- 必须具有长期记住程序、数据的中间结果及最终运算结果;
- 完成各种算术、逻辑运算和数据传送等数据加工处理;
- 根据需要控制程序走向,并能根据指令控制机器的各部件协调操作;
- 能够按照要求将处理的数据结果显示给用户。
为了完成上述的功能,计算机必须具备五大基本组成部件:
- 装载数据和程序的输入设备;
- 记住程序和数据的存储器;
- 完成数据加工处理的运算器;
- 控制程序执行的控制器;
- 显示处理结果的输出设备。
根据冯诺依曼的理论,我们只要把图灵机的几个部件换成电子设备,就可以变成一个最小核心的电子计算机,如下图:

靠地址总线寻找对应的“纸带格子”。读取写入数据由数据总线完成,而动作的控制就是控制总线的职责了。
3、更形象地将 HelloWorld 程序装入原型计算机
下面,我们尝试将 HelloWorld 程序装入这个原型计算机,在装入之前,我们先要搞清楚 HelloWorld 程序中有什么。
我们可以通过 gcc -c -S HelloWorld 得到(只能得到其汇编代码,而不能得到二进制数据)。我们用 objdump -d HelloWorld 程序,得到 /lesson01/HelloWorld.dump,其中有很多库代码(只需关注 main 函数相关的代码),如下图:

接下来,我们把这段代码数据装入最小电子计算机,状态如下图:

4、重点回顾
现代电子计算机正是通过内存中的信息(指令和数据)做出相应的操作,并通过内存地址的变化,达到程序读取数据,控制程序流程(顺序、跳转对应该图灵机的读头来回移动)的功能。
本文深入浅出地介绍了程序从源代码到计算机上运行的全过程。包括使用GCC编译器进行编译、链接的具体步骤,以及程序如何被加载到内存中执行的基本原理。
6656

被折叠的 条评论
为什么被折叠?



