一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第26天,点击查看活动详情。
前言
现在的开发者大多数都是使用高级的编程语言进行开发工作,高级的编程语言屏蔽了很多细节,让开发者更加专注到核心的业务逻辑中,都是使用现成的代码或者已经非常完善的工具包,所以现在的编程的入门门槛降低了很多,但是这是一把双刃剑,关键在于使用者是否能够正确的使用这一利器。高级的编程语言屏蔽的细节,在初级阶段会非常有帮助的,但是随着你开发年限的增长,如果你还在使用这些简单的编程工具包,那么就会造成危机,你无法深入到细节,或者遇到一个涉及底层的问题。你可能就束手无策了。所以我们要扒开表面,去深入了解底层的运作机制。
程序编码知识
在大学的刚学习计算机的阶段,大家都会接触到C语言的程序设计,C语言现在算是大多数高级编程语言的“父类”。包括像Java,C++都是模仿C语言的语法风格的。所以想要接触到底层的话,使用C语言作为示例是非常不错的。C语言的编译指令如下:
gcc -Og -o p p1.c p2.c
首先gcc就是GCC C编译器的,是Linux上默认的编译器,也可以使用cc来启动。-Og是一个优化等级的标志,-Og就是告诉编译器使用生成符合原始C代码整体结构的机器代码的优化级别,如果追求程序的性能的话,可以使用-O1或者-O2的高级别的优化等级,但是会造成生成的代码严重变形。人为可读性就很低了。
gcc使用该命令调用了一整套的程序,将源代码转换成可执行的代码,步骤如下:
- C预处理器扩展源代码,插入所有用#include命令指定的文件,并扩展所有用#define声明指定的宏
- 编译器产生两个源文件的汇编代码,名字分别为p1.s和p2.s
- 汇编器会将汇编代码转换成二进制目标代码文件p1.o和p2.o。目标代码是机器代码的一种形式,包含所有指令的二进制表示,但是还没有填入全局值的地址。
- 最后,链接器将两个目标代码文件与实现库函数(例如printf)的代码合并,并产生最终最终的可执行文件p
程序抽象概念
机器编程中有两种非常重要的抽象:
指令集体系结构或指令集架构(Instruction Set Architecture):定义了机器级程序的格式和行为,定义了处理器的状态。指令的格式以及每条指令对状态的影响。大多数ISA包括x86都将程序的行为描述成每条指令好像都是按照顺序执行的。一条指令执行结束后,下一条指令才开始执行。但是现实中处理器的硬件远比描述的精细和复杂。可以并发地执行多条指令。采取措施保证整体的行为和ISA指定的顺序执行行为完全一样。
巨大的字节数组:对于机器级程序来说,程序使用的内存地址是虚拟地追,看上去就像是一个非常巨大的字节数组。在底层由存储器系统将多个硬件存储和操作系统软件结合起来。
结论
明白这些抽象概念对于我们的理解非常有帮助的。