什么是汇编
指令系统
在了解什么是汇编之前,我们先要知道什么是指令系统。指令系统如其名所示,就是整个计算机所支持的全部指令的集合,比如说上一节提到过的ADD,MUL等等。这些指令从计算机看来都是机器语言,什么叫机器语言呢?
因为计算机作为一个数字系统[1],一般只能识别二进制码,也就是00100011000100···类似的二进制串,我们想要和计算机交互,让计算机运行我们想要的命令,那么我们就必须把我们的命令翻译成这一系列特定的二进制串,这些二进制串就叫做机器语言。
如果一个计算机支持了ADD指令,我这里拿一个具体的8051内核单片机[2]作为例子,8051单片机其中实现了加法运算ADDA,data,其对应的操作码的机器码,也就是ADD的机器语言表示是0x25,也就是0010,0101。也就是说,我们现在可以通过机器码和计算机进行一定的交互了,而计算机所支持的所有机器码便构成了整个指令系统。而指令系统现在多分为CISC和RISC两大体系。
CISC复杂指令集计算机
CISC(Complex Instructions Set Computer,复杂指令集计算机)指令系统的典型例子就是我们日常常见的IntelTM生产的CPU。复杂指令如同其名字所说,其指令系统所支持的指令都比较复杂,可以实现更多功能强大的操作,比如说直接从外部储存器中读取数值如图Figure1,写入数值等等,这些操作都是RISC指令集说不支持的。
Figure 1
RISC精简指令集计算机
RISC(ReducedInstructions Set Computer,精简指令集计算机)指令系统的典型例子就是我们移动平台比如手机,平板电脑等使用的ARMTM类型的CPU。它的指令如其名字所说,都是比较简单的,举个例子来说,比如CISC可以直接从内存中读取写入数值,但是RISC的就必须把数值从内存先加载到寄存器中,然后从寄存器中读取数值,这个过程如Figure 2所示。
Figure 2
RISC的指令精简意味着完成一个CISC直接支持的操作就必须通过多条指令间接完成,那么是不是就一定速度性能劣于CISC呢?不然,RISC的指令解码[3]和执行直接由硬件实现,我们称之为硬联逻辑,也就是说每条指令都会对应一个硬件电路去专门实现它,因此完成一条指令的速度将会快于CISC的。
因此RISC和CISC各有优缺点,不能一概说谁优谁劣,而且现在还出现了在CISC中搭配RISC内核的CPU。(鉴于RISC的指令形式比较简单,我们接下来出现的例子都将会是以ARM指令作为例子)。
汇编
说完了指令系统,那么我们就可以开始真正回答一开始的问题“什么是汇编”了。汇编(assembly language)也是一种编程语言,其出现的目的很直接,就是解决机器码难以记忆的难题。用一大串二进制码表示一条指令对于程序员来说,是一个不小的负担,而且出错了将会难以查找,因此就出现了汇编这种与机器码直接相关的低级语言,其本质就是用一些英文符号表示二进制串。
C语言与汇编的关系
C语言作为一种高级编程语言,其本身有着移植性较强(移植性与汇编语言对比较强,若是比起Java等语言则不如),易于理解,便于差错的优点。计算机自然是不能识别C语言本身的,计算机处理器C语言程序本质上还是处理一系列的二进制串,因此C语言必须通过一定手段解释为一些特定的机器码。我们就是通过汇编作为跳板,首先先将C语言编译成汇编语言,然后再将汇编语言编译成机器码实现的,这个过程框图如Figure3。这个过程的一个例子可以参考Figure4。
也就是说,对于C语言,其编译器是至关重要的一个东西,不同硬件平台上的编译器都将不同,而编译器的优化水平,编译水平将直接导致程序的效率高低等等。
Figure 3
Figure 4
最后想说的话
C语言是一个简洁优美的计算机编程语言,采用结构化编程的思想,其具有高效率[4],与底层硬件有一定关系的低级语言的特点,也有着编写的程序可读性高,运算符丰富,表达灵活,符合人类直观感觉的高级语言特点,比起汇编语言这类型的与硬件平台高度相关的低级语言,C语言具有强大的可移植性,也就是说你在A平台上写的代码可以经过很小的修改甚至完全不用修改就可以在B平台上使用。
C语言所有的指针操作可谓是C语言中的明珠,使用得当可以大幅度增大程序运行的效率,然而有利有弊,指针的使用要求使用者了解计算机的储存原理,不然无法很好的理解指针。在Java等高级语言中,虽说已经抛弃了指针这个概念,但是有个相似的引用这个东西。
在IT风云骤变的世纪,C语言已经走过了大半世纪,其中不知道见证了多少语言的诞生,兴盛与灭亡,而C语言依然坚挺,在2016世界编程语言排行中排名第二,说明了C语言的重要性。
Figure 5
而目前,编程语言成千上百,常见的有C,C++,Java,Python,Ruby,PHP,Lua,Perl,Fortran,Lisp,MATLAB等等,其适用于各种不同的场合,而我们可能经常会听到java,Python,PHP等等,因为他们的确是现在非常的热门,仿佛他们可以完成一切编程任务。其实不然,在我们的单片机,嵌入式开发中这些追求高效率的编程任务中,我们还是大量的使用C语言和C++语言,而不会采用java开发,特别是对于一些没有JVM的单片机,根本无法谈及Java等。而且,随着时代发展,C语言也从早期的ANSI C发展到了C89,C99,C11等,虽说不是每个编译器都支持了这些标准,但是也说明了C语言也在与时俱进,因此学习C语言不会落伍。
而且我认为,作为一个专业的电子工程的学生,以编程作为饭碗的人来说,不管你以后从事的工作将会使用什么语言进行编程开发,也许你以后永远都不会采用C语音作为开发的工具,学习C语言都将是你的首要选择。因为学习C语言能强迫你了解计算机的体系结构,计算机的组成原理,内存管理,数据结构等很多计算机基础知识,更重要的是,你可以从中学会从计算机的角度看待一个问题,而不是作为一个人的角度看待一个问题,这样听起来很抽象,但是学习下去诸位就会发现这个其实是很重要的,从计算机的角度看待问题可以使得计算机处理任务更加的高效,稳定。而现在的Java,Python等语言很多都是从人类的思维出发的,符合人类直觉,但是却不能让你了解到一些细节的东西。因此,我们又有什么理由放弃学习C语言呢?!
[1] 数字系统采用的数制倒不一定就是二进制的,比如初期的电子管计算机有些会采用十进制的,知道冯洛伊曼提出冯洛伊曼体系结构的之后,人们发现采用二进制的稳定性更高。因此现在的计算机一般都是二进制数字系统。
[2] 单片机也是计算机的一种,它是在芯片内部集成了除了CPU之外的很多常用外设和储存器,比如ADC,DAC,DRAM,Flash等等。
[3] 多由控制器负责指令的解码。
[4] 取决与其编译器,有些编译器的优化得好,其效率直逼手动汇编程序。