计算机语言翻译
什么是计算机语言?
1
日常生活中使用自然语言
顾名思义,计算机语言类似于汉语、英语,是一种用来传递信息的工具。
例如:日常生活中,使用汉语将自己想表达的思想传递给他人。
2
能否用自然语言和计算机“对话”?
众所周知,计算机最初的用途就是用于计算数据,例如:
我想知道123+456等于多少?
我可以用汉语对计算机进行提问吗?
一定有人会回答:可以啊!现在的语音助手可以实现这种功能。例如,Apple的Siri,小米的小爱同学,百度的小度,阿里巴巴的天猫精灵。
然而,看似简单的一问一答,却在计算机内部经历了一个非常复杂的步骤。
其中的一个非常重要的环节是:
通过自然语言识别和理解算法,让计算机理解了我们需要运行加法程序。接着把123和456放到计算程序里面,让它们相加。
得益于现代的人工智能学科的发展,让计算机看起来似乎可以理解我们日常生活中使用的自然语言了。
然而实际上,计算机却只是忠实地执行了固定的程序。
3
怎样直接和计算机“说话”?
我们暂时不探讨怎样让计算机理解自然语言,把中间的“人工智能”步骤去掉。
怎样让计算机能够直接理解我们想表达的内容呢?
很简单,答案就是:通过编程语言。
通过编程语言,我们可以键入对应语法,让机器通过代码来理解我们的意图。
4
计算机是如何思考的?
要和计算机直接沟通,那么我们就必须知道计算机是如何思考的?
让我们进入计算机的内部,看一看被称为计算机的核心CPU(中央处理器,central processing unit),是如何工作的?
CPU由三部分构成:
1、算术、逻辑单元:对数据执行运算(例如加法、减法)的电路。
2、控制单元:协调机器活动的电路。
3、寄存器组 :数据临时存储。
然而,寄存器能够存储的信息量很少,仅仅是当前工作所必要的大小。
鱼的记忆只有7秒,CPU的记忆恐怕是更短。总不能,CPU做一步操作,就把上一步操作的结果给忘了吧。
因此,我们需要内存来配合CPU进行数据操作。
大部分数据都存储在内存上,仅有当前正在处理的数据,才放到CPU的寄存器组上。
数据通过数据总线,在CPU和内存上进行传输。
接下来,我们来看看,将两个数据相加会经历哪些步骤:
1、从内存中取出一个加数,放到一个寄存器中。
2、从内存取出另一个加数,放到另一个寄存器中。
3、激活算术、逻辑单元中的加法电路,以前面两步的寄存器作为输入,用另一个寄存器存放结果。
4、将结果存放到内存中。
5
机器语言:最接近计算机运行本质
我们知道了,让计算机将两个数相加需要进行4个步骤。我们把这4个步骤告诉计算机,就可以实现加法操作了。
但是,计算机内部就是一大堆晶体管,每个晶体管有开和关两种状态。一般我们用1来表示开,用0来表示关。
也就是说,计算机能存储的是两种状态的数据,而十进制拥有0到9,十种状态。
很显然,十进制数据的状态太多,没法在计算机内表示。所以,首先我们需要把十进制的123和456转换为二进制数据。
123的二进制为1111011
456的二进制为111001000
现在,123和456被只有两种状态的二进制所表示了,满足计算机内部也只有两种状态的情景了。
123在计算机内部,被存储为晶体管状态——开开开开关开开。456被存储为晶体管状态——开开开关关开关关关关。
归根结底,计算机能存储和操作的是晶体管的状态组合。而这种状态组合中,每一个晶体管只有两种状态,与二进制数据一一对应。
而二进制又可以被转换为十进制。因此,计算机间接地计算了十进制数据。
数据在计算机中被存储为了晶体管状态,要完成运算,必须对数据进行操作。在前面的步骤中,我们做了两类操作。
一类操作是移动数据。例如,将加数放入寄存器1。另一类是激活加法电路。例如,将寄存器1,寄存器2的数据相加,并放入寄存器3。
很显然,要执行什么操作也必须以晶体管的开关状态来表示。我们很自然地会把它们也写成二进制形式,称之为操作码。
而操作数指明操作的更详细信息,例如,需要操作的数据本身,或者哪个寄存器包含需要操作的数据,哪个存储单元用于接收该数据。
操作码+操作数为一条指令。
操作码与操作数在数据上没有本质上的区别,它们都是二进制的数据。例如:CPU每次读取16位二进制,将前3个二进制作为操作码。其后都作为操作数。
这种以二进制表示对应的晶体管状态的方式,我们将其称之为机器语言。
当然,在纸上写好二进制之后,我们必须让其转化为晶体管状态。这里就设计到输入输出设备了。在早期人们会在纸带上打孔,用是否打孔来代表一个晶体管状态。之后,将打好孔的纸带放到机器中读取,将其转换为晶体管状态。如今,我们直接使用键盘在屏幕上输入即可。
6
汇编语言:助记词优化机器语言
单纯用0和1来写程序非常的困难。
于是,人们把机器语言中的操作码用一系列的英文单词来表示,将二进制写成十六进制。这就产生了汇编语言。
例如,把移动操作码,用单词mov来替代。把激活加法电路,用单词add来替代。使得程序更易于人们理解。
这样也必然会衍生出一个问题,计算机无法直接处理英语和十进制。因此,需要一个汇编器来作为“翻译”,将汇编语言“翻译”成由二进制表示的晶体管状态。
7
低级语言依赖CPU的具体实现
在编写机器语言或汇编语言时必须要注意:不同类型的CPU内部工作细节不尽相同。
个人电脑采用的是Intel、AMD出品CPU。而移动设备常常采用ARM系列的CPU。
在写机器语言时,会遇到很多差异性的问题。例如,寄存器的数量、作用不同,操作码的二进制表示不一致。或者,在一种CPU上有某种类型的操作码,但是在另一种CPU上却没有这种类型的操作码。而对应效果的操作,在后者上是由其他几种操作码+操作数组成的指令,分几步完成。
再看看汇编语言的情况呢?汇编语言是通过注记词来替代二进制表示的,如果用面向不同类型CPU的汇编器来“翻译”,确实可以解决一部分的操作码二进制不一样的差异。
但是,这仅仅是一小部分差异。因此,汇编语言也必须严格按照目标CPU来差异化编写程序,并且用对应的汇编器来“翻译”。
不管是机器语言还是汇编,在写程序前必须关注CPU的内部细节。运行在一种类型CPU上的代码,不能直接在另一种类型的CPU上直接运行。需要将其根据另一类CPU的工作细节进行修改,才能正常运行。
8
高级语言:不依赖具体指令集
现在你可以用机器语言或汇编语言写计算机程序了。如果你觉得为什么计算机语言如此复杂,那就对了。
机器语言或汇编语言忠实地描述了计算机的详细工作状态。因此,用机器语言或汇编写出来的计算机代码,详细操作了太多的细节了。
对人来说是十分不友好的,难以编写,调试。并且,也难以在多种类型的CPU上移植。
那怎么办呢?能不能有一个更好的办法,这时候高级语言应运而生。在机器上建立一个抽象层,通过抽象层表达意图。而避免直接描述具体的CPU工作细节。
我们用C语言作为示例,编写上面讨论的加法问题。代码如下:
int a, b, c;
123;
456;c = a + b;
printf(“%dn”, c);
在C语言中,我们声明了3个变量。将a赋值为123,b赋值为456。将a、b相加,加法的结果赋值给c。
可以看到,在C语言中,我们不关心a,b,c存在内存上的哪个地方。也不用加法操作码add那些的。反而,C语言的表述方法和人类的认知十分接近。
和汇编一样,计算机也无法直接理解高级语言,并且C语言不描述CPU具体工作细节,而是描述了一个抽象过程。没法像汇编那样简单地把英文根据目标CPU替换成二进制状态了。
而是通过两个更为复杂的过程,将高级语言转换为机器语言,这两个步骤分别为“编译”和“链接”。
这样一来,高级语言与计算机的硬件结构及指令系统无关。在个人电脑上编写好的程序,也可以拿到移动设备上来使用。并且,它有更强的表达能力,可方便地表示数据的运算和程序的控制结构,能更好地描述各种算法,而且容易学习掌握。
C语言就是众多高级语言中,应用最广的一款语言。
END
欢迎大家关注我的微信公众号:小杰码匠
2021全新C语言系列课程持续更新中……
扫码关注我们
2021年全套C语言系列课程,尽在小杰码匠!