机器级编程——编码基础知识

226 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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指定的顺序执行行为完全一样。

巨大的字节数组:对于机器级程序来说,程序使用的内存地址是虚拟地追,看上去就像是一个非常巨大的字节数组。在底层由存储器系统将多个硬件存储和操作系统软件结合起来。

结论

明白这些抽象概念对于我们的理解非常有帮助的。

参考资料

深入理解计算机系统