第1节 计算机的语言:指令集
我终于明白“兼容性”是怎么回事了。这是指我们得保留所有原有的错误。
——丹尼·塔塞尔(Dennie van Tassel)
Intel 4004指令集,开启微处理器时代
软件编码规范:什么是指令集?
指令集是CPU运行的软件的二进制编码格式
指令集又称为指令系统架构(Instruction System Architecture,ISA),是CPU运行的软件的二进制编码格式,是一种指令编码的标准规范。由于硬件电路都是由晶体管组成的,只能识别0、1(二进制),因此CPU上运行的软件必须有一种编码格式来让CPU识别,如图2.1所示。
图2.1 指令集、软件和CPU的关系
每一个CPU能理解的指令集都是由一组“指令”组成的。在CHN-1计算机中,指令只有两种,即0代表“关”、1代表“开”。因此可以说CHN-1的指令集只包含两条指令。CHN-1运行的软件就是由0、1组成的连续指令序列。
CPU企业都会对所制造的CPU提供详尽的指令集手册材料。一般说到某种指令集时,我们头脑中浮现的都是“Instruction Reference Manual”之类的文档材料。
指令集是软件和硬件的接口。从软件人员的视角来看,指令集严格规定了CPU的功能,指令集也反映了软件人员对CPU进行编程的接口,所以有时候指令集也称为“处理器架构”。
这里简单介绍目前最常用的指令集。台式计算机、服务器主要采用x86指令集,手机、平板电脑主要采用ARM指令集,龙芯计算机[2]采用自定义指令集LoongArch。
[2] 本书中的龙芯计算机指搭载龙芯处理器的计算机。
什么是指令集的兼容性?
兼容的CPU能运行相同的软件
运行相同指令集的CPU称为“兼容的”。这里的“兼容”主要是指CPU可以识别相同的指令编码,因此可以运行相同的上层软件。
例如,如果不同的厂家制造的计算机都采用和CHN-1相同的指令集,那么这些计算机都能运行相同的软件,是一类“兼容机”,如图2.2所示。
图2.2 兼容机遵循相同的指令集
而在CHN-2计算机中,指令的编码格式发生了变化,每条指令变成4个二进制位,其中每一位包含一种显示汉字的信息。这要求CHN-2计算机的数据通路、存储器、指令寄存器、运算器都要每次处理4位二进制,显然CHN-2计算机上的软件是无法直接在CHN-1上运行的。所以CHN-2和CHN-1是“不兼容”的计算机。
为什么指令集要向下兼容?
成功的CPU系列能保持几十年兼容
兼容性在CPU生态中具有重要的意义,一个良性发展的生态是在兼容的指令集基础上制造出更多计算机、开发出更多应用软件。有生命力的CPU企业都会非常看重CPU指令集的稳定性,向指令集中添加、删除指令都非常小心谨慎。如果指令集发生变化,很容易因为设计上的疏忽而引入“不兼容”问题,导致以前的软件无法在新的计算机上运行,那么新的计算机是不会被用户购买的。
那么指令集就永远不变了吗?也不是这样的。时代的发展总是要求计算机实现更多功能,指令集也应该与时俱进。
人们在实践中找到一种比较好的折中方法,既能够保持兼容性、又能够让指令集越来越强大。这个方法就是“增量演进、向下兼容”。“增量演进”的意义是,指令集的发展只能添加新的指令,不允许删除现有的指令,也不允许改变现有指令的功能。这样做的好处是,以前的软件一定能够在新指令集的CPU上运行,新的CPU能够“继承”以前全部的软件成果。坚持这样的路线,新的计算机一定能够对老的计算机实现“向下兼容”(有的书上也叫“向前兼容”)。
IBM公司在1964年推出的System/360系列计算机是“兼容机”概念的始祖,如图2.3所示。在此之前的计算机制造商,经常在新型号计算机中添加不兼容的新特征,导致老型号计算机上的软件不能在新型号计算机上运行。而属于System/360系列的计算机都能够运行相同的软件,最大化沿用了用户的软件资产。直到今天,IBM仍然在制造兼容System/360系列的大型机。
图2.3 “兼容机”概念的始祖System/360系列计算机
计算机界有一个经典的例子,CPU厂商由于不坚持向下兼容而吃苦头,你可能想不到这个故事的主角是Intel。在2001年之前,Intel的桌面和服务器计算机都采用32位的x86指令集。这个“32位”可以理解为一次运算所处理的数据的最大宽度。随着多媒体技术以及互联网的快速发展,市场对64位架构的需求日益强烈。Intel与惠普公司共同开发了64位指令集,称为IA64,又称英特尔安腾架构(Intel Itanium Architecture)。几乎同时,AMD公司也开发了64位的指令集,称为AMD64。由于IA64与32位x86指令集不兼容,而AMD64则对32位x86指令集向下兼容,因此市场上的消费者更喜欢AMD64。事实上,后来Intel也被迫放弃了IA64,采纳了AMD64指令集并改名为x86-64,形成当今真正主流的64位x86架构。由这个例子可以看到,即使是Intel这样强势的企业也不得不在“向下兼容”的市场铁律前折服。
为什么说指令集可以控制生态?
软件生态的价值大于CPU
指令集承载了一个软件生态,也是软件生态的源头(见图2.4)。假定有一个CPU企业,不妨称为A公司,想要设计CPU并投放市场,那么一定是从设计指令集开始的。A公司首先设计了一种新的指令集ISA-A,制造出兼容ISA-A的CPU,并将生产的CPU安装到计算机中,然后为这种CPU开发相关的操作系统、编译软件(也称为工具链)。而应用软件开发者只需使用编译软件对源代码进行编译,生成二进制码,就可以在这种CPU上运行软件。日积月累,在这种CPU上运行的软件越来越多,生态也越来越庞大,A公司就可以通过销售CPU获取大把利润。
图2.4 从指令集构建软件生态
生态的规模越大,吸附能力越强。当生态发展到一定规模时,会吸引更多的CPU厂商加入这个生态阵营,生产兼容ISA-A的CPU并销售。这些CPU都能够运行这个生态里的所有软件,用户可以择一购买。
这时候,最早设计这种指令集的厂商A公司就开始发现,很多公司都来分切这块蛋糕,原来A公司一家独享的市场被切成几块。A公司辛辛苦苦建设生态,最后只沦为铺路人。长此以往,将没有人愿意做建设生态的工作。
为了保护市场先行者的利益,鼓励技术创新,知识产权法规对指令集有保护制度。CPU指令集可以通过申请专利的形式获取专利权,任何人在付出一定条件的前提下才有权使用指令集。
有了指令集的保护制度,A公司就可以对ISA-A指令集开展知识产权保护工作。现在,A公司可以放心地销售CPU、建设生态,因为其他公司只有得到A公司的商业授权,才能生产和ISA-A相兼容的CPU,也只有获得授权后才能在市场上销售。在没有取得授权的情况下生产、销售与ISA-A相兼容的CPU,是对A公司的侵权,是不符合法律规定的。
A公司通过对指令集的把控,设定了生态的进入门槛。A公司可以在这个生态中拥有自己的话语权,也可以决定哪些CPU企业可以进入这个生态。越是强势的CPU企业,对授权的条件越严格,取得授权的门槛也越高。像Intel、ARM这些公司的授权费用可以高达上亿元。
反之,如果A公司不重视指令集的保护,利用指令集对软件生态进行控制的价值就会丧失;另外,因为知识产权保护有固定的年限,超过一定时间其就不再受到保护。
应该说,知识产权对保护先行者的利益、刺激技术创新,是发挥了正面作用的。
自己能做指令集吗?
做指令集不难,难的是做软件生态
指令集是一个标准规范。表面上看,“做指令集”的成果形式就是写出了一份文档。设计一个指令集不算什么高难度的事情,和做一个CPU动辄需要几年工夫相比,它可能几个月就能完成。
但是放眼望去,全世界常用的指令集种类很少,拥有大量用户的主流指令集不超过10个。为什么会这么少呢?
首先,做指令集不难,难的是做软件生态。把CPU做出来只能算是第一步,还需要在这种CPU上开发越来越多的软件,这样才能让CPU的使用价值更大。然而,现在的软件开发是很耗成本的工作,高质量软件的销售价格很容易就超过计算机硬件。软件厂商面对一种新指令集时,很难有动力为其投入成本做开发。尤其是在指令集刚推出、还没有多少用户的阶段,如何吸引软件厂商是很难解决的问题。很多指令集本身设计得很好,只是因为没有打破“没用户—没厂商—没用户”的双向悖论而迟迟不能打开局面。
其次,高端CPU需要的指令集已经非常复杂,远远超过简单CPU。对于只做简单控制类工作的嵌入式CPU、微控制器CPU,可能几十条指令就够用了。但是对于在台式计算机、服务器中使用的CPU,往往需要上百条甚至更多的指令。尤其是像电源管理、安全机制、虚拟化、调试接口这些技术,设计指令集时必须和CPU内部架构、操作系统进行统筹考虑。有时候甚至需要把CPU、操作系统的原型都开发出来,经过长期测试验证才能保证指令集的设计达到完善程度。
因此,敢于推出新指令集的企业往往都是一流的CPU公司,而这要靠雄厚的资金实力和足够的研发投入。龙芯采用自定义的指令集,迈出了勇敢的一步。