第二章 编码与计算机的语言
第二章 编码与计算机的语言
本章中涉及的几个编码表中的内容是不严密的,目的在于说明编码的原理,不能将编码表中的内容拿来设计程序。
一、语言
● 如果我对您说:“给我一个苹果。”您会说:“好的”。 ● 如果我对您说:“Give me an apple.”您也许会说:“OK.”也许会说:“说国语行吗?”
● 如果我对您说:“@#$%^&*”您一定会说:“我听不懂。” 上面三句话说明了一个道理:人与人之间沟通一定要用双方都懂的语言;如果您用了一种对方不懂的语言与其沟通,那么您一定得不到想要的结果。
不难想象,语言是一种能让人或机器读懂的东西。 什么!还有能让机器读懂的东西?是的,真的存在“机器语言”这种东西,可以让计算机读懂。
人的语言是用声音、手势、文字等形势表现出来,机器语言用什么形式表现出来呢?因为计算机由大量的电子元件与导线组成,只有电信号才能激发它工作,所以计算机能读懂的机器语言自然是“电信号”,也就我们熟悉的“指令”。由此可以得知,机器语言是CPU 提供的所有指令的大集合,就好像我们的汉语字典一样。
我们人类会把语言中的各个文字合理地组合在一起,表示给其他人,让对方知道一些信息甚至去做一些事情。我如
何组织语言中的文字是很重要的。如果我组合得不合理,那么一定达不到我的目的。同理如果我们把计算机语言中的各指令合理地组合在一起,展示给计算机,那么计算机就会实现我们想要的功能;如果我组织得不合理,那么计算机也就会做出不可理喻的事情来。
机器语言是指令的大集合,而程序是指令的组合,二者有什么区别呢? 机器语言是人类罗列出来的计算机能读懂的各种指令。程序则是将各种指令有“有组织、有纪律”地组合在一起,从而促使计算机执行这些指令,从而完成某些功能。
二、简单的编码
如果我对您说:“000 001 010 011 100 101”,您一定还会说“听不懂。”
如果我说这话之前给您一张纸,上面写着如下东西(表
2.1): 给 我 一 个 苹 果 好 的 000 001 010 011 100 101 110 111
表2.1 一张“莫名奇妙的表”
您看了后,我再和您说:“000 001 010 011 100 101”您就会知趣地回答我:“110 111”
刚才,我为什么要如此大费周折地与您交谈?是的,与您如此交谈的确没必要。可与计算机交谈就不同了,它只能
读懂类似上面那些“0”和“1”组成的“0-1串”,并把“0-1串”转化成对应的“电信号”,这些转化出来的“电信号”就是CPU 能识别的指令。
上面那张“莫名奇妙的表”号称“编码表”。 一个编码表由两部分组成:一部分由并列在一起的“不同事物”组成。如表2.1中不同的汉字。另一部是与这些不同事物一一对应的“代替编码”组成。如表2.1中的“000”、“001”等。这些“代替编码”被简称为“代码”。 制作编码表的过程分为三个步骤:第一、准备“不同事物”与“代码”两种东西;第二、将两种东西指定“一一对应关系”;第三、将“不同事物”与“代码”按照“一一对应关系”填入表中。
制作编码表的过程被我们称为对某类事物“编码”。在这个制作过程中,我们指定了与不同事物形成一一对应关系的“代替编码”(简称代码)。 在本书中,如果“编码”一词如果作为动词使用,那么其涵义就是“为不同事物指定代替编码”的动作,即“制作编码表”的动作;如果“编码”一词作为名词使用,那么其涵义就是“编码表中的代替编码”,即“代码”。
制作编码表要遵循的规则是:第一、编码表必须包含“不同事物”与“代码”两部分;第二、编码表中的“代码”与“不同事物”必须是一一对应关系。“一一对应”指出了一....
个事物有且仅有一个与众不同的代码。如表2.1中的不同事........
物是:各种汉字。每个汉字都对应着一个与众不同的代码。
从编码表的制作规则中可得知:既然代码是代替编码,那么就必须知道代码所代替的事物,否则代码就没有意义。这好像我们用的数字“1,2,3……”一样,只有用它们来数苹果时,它才具有了意义,否则我们不知道“1”是代表着1个苹果还是“1”筐苹果。
掌握了制作编码表的要领,我们可以为各种我们需要的事物制作编码表了。下面就看看我为CPU 功能制作的编码表(表2.2): CPU 功能
代码 加法功能 电信号1 减法功能 电信号2 …… ……
表2.2 代表CPU 功能的编码
明白吗?电信号1激发CPU 的加法功能,电信号2激发CPU 的减法功能(至于电信号1与电信号2都是什么样的电信号我在后面的章节中讲解,虽然电信号不是能书写出来的东西,但是没有规定代码就一定是能书写的东西。),而且您不要忘了,这些电信号就是指令。如果您明白了,再看看我对表2.2中的指令(也就是表2.2中的电信号)的进一步编码(表2.3):
指令
代码
电信号1 00000001 电信号2 00101001 …… ……
表2.3 代表指令的编码
结合表2.2与表2.3,就可以得知,要想让CPU 执行加法功能,需遵循的步骤是:第一、将表2.3中的代码“00000001”送入计算机;第二、计算机收到此代码后会将其转化为“电信号1”;第三、计算机自动将转换出来的“电信号1”送入CPU;第四、CPU接收到“电信号1”,执行加法功能。
别忘了,构成程序还有另外的一部分:数据。
要想让CPU 认识并处理数据必须经过如下的过程:第一、把数据编码成“0-1串”代码送入计算机;第二、计算机将这些代表数据的“0-1串”转换成电信号发送给CPU。您不愿意也没有办法,因为计算机只会将“0-1串”转化成电信号,不会将包含有除“0”和“1”之外的任何程序代码转化为电信号,而CPU 只认识电信号。
所以,要让CPU 处理数据,还要对数据进行如下的编码(表2.4): 数据
代码 1 00000001 …… …… 41 00101001 …… ……
表2.4 代表数据的编码
有了上面的编码的知识,相信大家能轻易看懂这张对数据的编码(表2.4)。
我想是时候来讲一讲程序代码与CPU 指令的区别了:
1、代码包含“代表指令的编码”与“代表数据的编码”
两部分。其中“代表指令的编码”并不是指令本身(指令本身是一个电信号),而是对指令实施编码后,在编码表中与该指令对应的代码。“代表指令的0-1串编码”被称为“指令0-1串”“代表数据的0-1串编码”,被称为“数据0-1串”。
2、指令是能激发CPU 完成某个功能的电信号,而代码是能转化成电信号的“0-1串”,转化成的电信号有可能是指令,也有可能是数据。
回顾表2.4,会发现一个问题。由于涉及到了三个编码表,所以我们好好捋一下:结合表2.3与表2.2的对应关系得知:“00000001”对应“指令1”,“指令1”就是“信号1”,“信号1”对应CPU 的“加法功能”。根据这一系列的对应关系,我可以得知“00000001”对应CPU 的“加法功能”。再看表2.4,“00000001”对应着数值“1”。问题就在这里:同一个“00000001”对应着“1”(属于数据)和“指令1”(属于指令,代表“加法功能”)两种事物,CPU不会将它们弄混吧!
答案是:在程序编写没有错误的情况下,CPU就不会弄混,否则就说不清了,CPU 不会自动区分。让我们欣慰的是,只有“指令0-1串”与“数据0-1串”之间才会出现重复现象,而不同的指令是不可能对应着相同的“指令0-1串”的,同理,不同的数据也不会对应相同的“数据0-1串”。
以过以上的讲解,我们知道了通过“0-1串”代码可以
与计算机进行沟通,所以我现在可以对机器语言下进一步的定义了:
机器语言:将CPU 的指令与数据编码成“0-1串”,这些“0-1串”构成了机器语言。
三、低级语言
计算机语言不是只有一种机器语言,还有汇编语言、C语言、Basic语言等等。计算机语言被人们划分为三类:机器语言、低级语言和高级语言。上一节已经讲过了机器语言。这一节主要讲解低级语言,并简要介绍一下高级语言。
当您看到表2.3和表2.4时一定有种头大的感觉。因为每一个代码都是一长串“0”与“1”的组合,难于记忆。如果您有用机器语言编程的经历,您一定还知道另一个困惑:编程过程中,一旦哪里写错了想更正过来,很难找到错误的位置。出于这些原因,计算机的低级语言应运而生。
请看表2.5: 指令0-1串 00000001
代码 add 00101001 sub …… ……
表2.5 代表“指令0-1串”的编码
表2.5对“指令0-1串”进行了编码,也就是对每个“指令0-1串”都用一个形象的代码代替。有了这种替换,程序代码的编写就不再用“0-1串”了,改为上表中的add,sub等代码了。表2.5中的代码部分就是低级语言的主要构成部
分,就好像表2.3与表2.4中的“0-1串”代码构成了机器语言一样。这些诸如“add、sub”之类的代码被称为低级语言的指令,很显然,低级语言的指令与CPU 的指令是一一对应的。
这样做的好处是显而易见的:易于背记、易于排错等等。可是另一个问题又出现了:计算机只认识“0-1串”,不认识add,sub什么的,怎么办?
因为这个问题的存在,一种东西诞生了。它是一个翻译家,会将add,sub等代码一对一地翻译成“0-1串”。
这份翻译工作并不可小视,它虽看起来简单,可工作量很大,所以这份工作被交给了计算机来完成。可计算机如何来完成?当然是做成程序来完成。这个程序怎么编写出来的?当然是用“0-1串”。这种程序在上个世纪就被聪明的工程师们编写出来了,而且还为它取了一个好听的名字,叫做“编译器”。
编译器不仅翻译“指令0-1串”,也会翻译“数据0-1串”。从它的名字上可看出,它做的工作应该不只是翻译工作,还有其它的,否则就叫成“翻译器”了。那么它还会做什么呢?
在编写程序过程中,人们发现,CPU的工作逻辑与人类的工作逻辑非常不同,所以就设计了更符合人类逻辑的代码书写方式。那么编译器的工作就有两个了。如下:
首先、“编”。将这种人类思维方式写出的代码转换成CPU 的工作方式的代码;
其次、“译”。将第一步中转换出来的代码逐条翻译成 “0-1串”代码。 当我们在用低级语言编写程序时,会发现一些代码并没有对应着CPU 的什么指令,这些代码被称为低级语言的“伪指令”,它是编译器在“编”的过程中需要用到的,当“编”的工作执行完成后,这些“伪指令”就被编译器删除了,并不会参与程序的执行。低级语言的构成成份中,除了指令、伪指令,还有数据。
本章中一直提到的“0-1串”就是机器语言;低级语言一般指汇编语言;像C 语言、Basic语言等被称为了高级语言。各种低级语言、高级语言都有对应的编译器,编译器的主要工作就是将低级语、高级语言代码翻译成机器语言代码(0-1串代码)。
计算机能识别的只有机器语言。用任何低级语言、高级语言编写的程序必须用相应的编译器编译成机器语言的版本才能执行。
高级语言更贴近人类的思维方式;低级语言更贴近CPU 的工作方式。
用低级语言编写的程序代码由指令、伪指令和数据构成。高级语言没有指令、伪指令和数据的概念,因为发明高级语
言的目的之一就是避免程序员再去考虑CPU 的计算细节。
下面我将代码、程序、指令、“0-1串”的概念用程序的编写、生成、执行的过程串起来,以巩固这两章的内容(如图2.1)。
图2.1 程序的编写、生成、执行
在本章,主要讲解了编码的原理,同时用编码的原理阐述了利用计算机低级语言从编写程序代码至程序执行所需经过的主要过程。
编码虽是个简单的事情,可是把这些“代替计算机指令与数据的编码”拿来运用就不容易。就好像汉字人人都会写,既便不会写也会到字典中去查,可是您查完后就一定会不出差错地用好吗?