早期编译器是如何开发的
‘壹’ 编译技术的发展历程
1954年至1957年间,IBM的John Backus带领一个小组开发FORTRAN语言及其编译器,使得上面的担忧不必要了。
但由于当时处理中所涉及到的大多数程序设计语言的翻译并不为人所掌握,所以这个项目的成功也伴随着巨大的辛劳。
几乎与此同时,人们也在开发着第一个编译器,Noam Chomsky开始自然语言结构的研究。使得编译器结构异常简单,甚至还带有了一些自动化。
Chomsky的研究导致了根据语言文法(grammar,结构规则)的难易程度以及识别它们所需的算法来为语言分类。文法有4个层次:0型、1型、2型和3型文法,且其中的每一个都是其前者的专门化。2型(或上下文无关文法context-free grammar)是程序设计语言中最有用的,代表着程序设计语言结构的标准方式。
人们接着又深化了生成有效的目标代码的方法,这就是最初的编译器,它们被一直使用至今。人们通常将其误称为优化技术(optimization technique),但因其从未真正地得到过被优化了的目标代码而仅仅改进了它的有效性,因此实际上应称作代码改进技术(code improvement technique)。
在70年代后期和80年代早期,大量的项目都关注于编译器其他部分的生成自动化,这其中就包括了代码生成。这些尝试并未取得多少成功,这大概是因为操作太复杂而人们又对其不甚了解。
‘贰’ 编译器一般由哪种语言开发
其实我在想为什么汇编语言生成一个简单的编译器后,可以用新生成的编译器再次生成编译器,例如,C语言开发C的编译器呢?
这是一个递归的思想,举个例子一看就明白了
用一个大的模具可以生成一个A模具,A模具可以做出来B模具,依次往下推,最终这个小模具可以做出来小盒子用来装东西。
第一个大模具肯定是手工做出来的第一个模具,但是有了这个大模具后,后面就可以用他自动的生成更多的模具,后面的各种模具加起来又可以造出来更精致的模具,
所以,自动第一个大模具造出来模具的时候,大模具就可以被抛弃了。
我们都知道编译程序通常分为下面五个阶段:
1)词法分析
2)语法分析
3)语义分析与中间代码产生
4)优化
5)目标代码生成
当然最难的一点就是目标代码的生成,这一阶段实现了最终的翻译,就是真正把原码翻译成可以被CPU直接计算的机器码(NativeCode)。
‘叁’ 计算机语言是如何开发出来的
计算机语言是“设计”出来的,设计只需要思考和写文档,而该语言的编译器才是“开发”出来的。编译器也是程序,所以也需要用编程语言来编写,至于用什么语言就随开发者的便了。很多编程语言是用别的更基础的语言开发的,其中用最多的就是C语言。C语言编译器很多,大部分都是用别的C语言编译器编译出来的,而最早的C语言编译器是用汇编语言写出来的,最早的汇编语言编译器是通过“编译器自举”开发出来的。
相关回答
一个很深奥的问题
一、新建项目 启动Microsoft Visual Studio 。NET,新建一个C#项目MyApp,本例工程存放于F:\Csharp\MyApp。 二、添加控件 在Form1 窗体上添加三个控件(见图1):主菜单MainMenu、标签Label1和按钮Button1。
Label1和Button1控件的属性均采用缺省设置。MainMenu控件中添加三个菜单项menuItem1、menuItem2、menuItem3。Text属性分别设为“语言”、“中文”和“English”。
menuItem2、 menuItem3 的RadioCheck属性设为True。 图 1 三、创建配置文件 在项目中添加一个文本文件 i,保存当前程序的语言版本设置。该文件中只有一行内容。
如果是“English”,则表示程序为英文版;如果是“Chinese”则为中文版。这里暂且保存为“English”。 四、创建资源文件 。NET中的资源文件有三种: 文本(。txt )文件、XML 格式的。
‘肆’ 最早的编程软件是怎么来的
最早的没有现在意义上的编译器,是靠打孔器打纸带编程。大型机靠读纸带执行程序。
由于机器语言由0、1组成,难以阅读。所以在机器语言的基础上开发了汇编语言。最早的汇编语言编译器应该是机器语言编写的。一旦第一个汇编语言编译器开发出来以后,以后的版本都可以用汇编语言来编写了。
由于汇编语言还是很难使用,所以开发出高级语言。也可以预见,第一个高级语言编译器是由汇编语言编写的。有了第一个高级语言编译器,以后的高级语言编译器便可以用这个高级语言编译器生成。
也就是说,现在我们使用的C++语言编译器,可以用C++语言来编写。
‘伍’ 编译原理的发展历程
在20世纪40年代,由于冯·诺伊曼在存储-程序计算机方面的先锋作用,编写一串代码或程序已成必要,这样计算机就可以执行所需的计算。开始时,这些程序都是用机器语言 (machine language )编写的。机器语言就是表示机器实际操作的数字代码,例如:
C7 06 0000 0002 表示在IBM PC 上使用的Intel 8x86处理器将数字2移至地址0 0 0 0 (16进制)的指令。
但编写这样的代码是十分费时和乏味的,这种代码形式很快就被汇编语言(assembly language )代替了。在汇编语言中,都是以符号形式给出指令和存储地址的。例如,汇编语言指令 MOV X,2 就与前面的机器指令等价(假设符号存储地址X是0 0 0 0 )。汇编程序(assembler )将汇编语言的符号代码和存储地址翻译成与机器语言相对应的数字代码。
汇编语言大大提高了编程的速度和准确度,人们至今仍在使用着它,在编码需要极快的速度和极高的简洁程度时尤为如此。但是,汇编语言也有许多缺点:编写起来也不容易,阅读和理解很难;而且汇编语言的编写严格依赖于特定的机器,所以为一台计算机编写的代码在应用于另一台计算机时必须完全重写。
发展编程技术的下一个重要步骤就是以一个更类似于数学定义或自然语言的简洁形式来编写程序的操作,它应与任何机器都无关,而且也可由一个程序翻译为可执行的代码。例如,前面的汇编语言代码可以写成一个简洁的与机器无关的形式 x = 2。
在1954年至1957年期间,IBM的John Backus带领的一个研究小组对FORTRAN语言及其编译器的开发,使得上面的担忧不必要了。但是,由于当时处理中所涉及到的大多数程序设计语言的翻译并不为人所掌握,所以这个项目的成功也伴随着巨大的辛劳。几乎与此同时,人们也在开发着第一个编译器, Noam Chomsky开始了他的自然语言结构的研究。他的发现最终使得编译器结构异常简单,甚至还带有了一些自动化。Chomsky的研究导致了根据语言文法(grammar ,指定其结构的规则)的难易程度以及识别它们所需的算法来为语言分类。正如现在所称的-与乔姆斯基分类结构(Chomsky hierarchy )一样-包括了文法的4个层次:0型、1型、2型和3型文法,且其中的每一个都是其前者的专门化。2型(或上下文无关文法(context-free grammar ))被证明是程序设计语言中最有用的,而且今天它已代表着程序设计语言结构的标准方式。
分析问题( parsing problem ,用于限定上下文无关语言的识别的有效算法)的研究是在20世纪60年代和70年代,它相当完善地解决了这一问题, 现在它已是编译理论的一个标准部分。它们与乔姆斯基的3型文法相对应。对它们的研究与乔姆斯基的研究几乎同时开始,并且引出了表示程序设计语言的单词(或称为记号)的符号方式。
人们接着又深化了生成有效的目标代码的方法,这就是最初的编译器,它们被一直使用至今。人们通常将其误称为优化技术(optimization technique ),但因其从未真正地得到过被优化了的目标代码而仅仅改进了它的有效性,因此实际上应称作代码改进技术(code improvement technique )。
这些程序最初被称为编译程序-编译器,但更确切地应称为分析程序生成器 (parser generator ),这是因为它们仅仅能够自动处理编译的一部分。这些程序中最着名的是 Yacc (yet another compiler- compiler),它是由Steve Johnson在1975年为Unix系统编写的。
类似地,有穷自动机的研究也发展了另一种称为扫描程序生成器 (scanner generator )的工具,Lex (与Yacc同时,由Mike Lesk为Unix系统开发的)是这其中的佼佼者。在20世纪70年代后期和80年代早期,大量的项目都关注于编译器其他部分的生成自动化,这其中就包括代码生成。这些尝试并未取得多少成功,这大概是因为操作太复杂而人们又对其不甚了解。
编译器设计最近的发展包括:首先,编译器包括了更为复杂的算法的应用程序,它用于推断或简化程序中的信息;这又与更为复杂的程序设计语言(可允许此类分析)的发展结合在一起。其中典型的有用于函数语言编译的Hindle y - Milner类型检查的统一算法。
其次,编译器已越来越成为基于窗口的交互开发环境(interactive development environment,IDE )的一部 分,它包括了编辑器、链接程序、调试程序以及项目管理程序。这样的IDE的标准并没有多少, 但是已沿着这一方向对标准的窗口环境进行开发了。
‘陆’ 第一个编译器是靠什么编出来的
程序并不是一定需要进行编译才能运行的。可以直接对硬件通过指令集进行操作。
只是这种方法非常耗费时间,不易维护,对于普通开发人员提高了门槛。所以在此基础上,提供了一个“翻译”软件,将编程语言翻译成指令集。能够通过更加贴近人类语言的方式操作硬件。
‘柒’ 请问,编译软件最早是由谁发明出来的
Grave of Grace
后记
Grace Hopper是个非常amazing的人 (常被称为Amazing Grace),崇拜她的人相当多。虽然她的事迹很多,但是还有很多有类似事迹的人并没有像她这样受到众人的崇拜。由其中一点我们可以看出来:从1947年开始 (二战结束后第二年),她获得了第一个荣誉博士学位 (宾州大学),从那以后,她先后被40多所大学授予荣誉博士学位,其中包括芝加哥大学、华盛顿大学、马里兰大学等知名学府。各种妇女社会团体和学术组织都曾授予Grace各种称号和奖励。1991年,布什总统在白宫授予她的“美国国家技术奖” (National Medal of Technology) 是其中的最高奖项,她也是至今惟一获此殊荣的美国女性。她的名言有很多,她自己最喜欢的,也是她最喜欢对所谓的“年轻人”说的 (在她年老时,她所谓的年轻人就是“年龄不到我的一半的人就叫做年轻人”),这句话是:
“A ship in port is safe, but that is not what ships are built for.”
语录
下面Grace的语录中有几句比较有意思的话。
From then on, when anything went wrong with a computer, we said it had bugs in it.
The most dangerous phrase in the language is, “We’ve always done it this way.”
Humans are allergic to change. They love to say, “We’ve always done it this way.” I try to fight that. That’s why I have a clock on my wall that runs counter-clockwise.
Leadership is a two-way street, loyalty up and loyalty down. Respect for one’s superiors; care for one’s crew.
One accurate measurement is worth a thousand expert opinions.
Someday, on the corporate balance sheet, there will be an entry which reads, “Information”; For in most cases, the information is more valuable than the hardware which processes it.
We’re flooding people with information. We need to feed it through a processor. A human must turn information into intelligence or knowledge. We’ve tended to forget that no computer will ever ask a new question.
To me programming is more than an important practical art. It is also a gigantic undertaking in the foundations of knowledge.
They told me computers could only do arithmetic.
In pioneer days they used oxen for heavy pulling, and when one ox couldn’t budge a log, they didn’t try to grow a larger ox. We shouldn’t be trying for bigger computers, but for more systems of computers.
Life was simple before World War II. After that, we had systems.
We went overboard on management and forgot about leadership. It might help if we ran the MBAs out of Washington.
At any given moment, there is always a line representing what your boss will believe. If you step over it, you will not get your budget. Go as close to that line as you can.
I seem to do a lot of retiring.
I handed my passport to the immigration officer, and he looked at it and looked at me and said, “What are you?”
参考
维基网络:
http://en.wikipedia.org/wiki/Grace_Hopper
国立中央大学数学系:
http://li.math.ncu.e.tw/bcc16/pool/3.06.shtml
耶鲁大学计算机系:
http://cs-www.cs.yale.e/homes/tap/Files/hopper-story.html
计算机先驱:
http://202.207.0.245:9001/jisuanjifazhanshi/xianqu/18.htm
This entry was posted in网络3Cand taggedcompiler,debug,Grace Murray Hopper,传记,发明,编译器,起源. Bookmark thepermalink.Post a commentor leave a trackback:Trackback URL.
‘捌’ 最早的C语言编译器是什么做的
汇编。这真的是最早最早的。
准确的来说,这和编译器的开发有关,不用说太细,很麻烦怕你不懂。你现在假设第一个编译器是用会变写出来的,它的功能很简单,就是解释简单一种类似于C语言的高级语言,但是这种所谓的高级语言还没有完全拥有C语言的所有特性。只有比较简单核心功能,比如能把文本文件的高级语言转换成机器代码并且执行。
有了这个原型之后,就可以用这个编译器来解释简单C程序,就可以用C重写编写一个新的编译器,这样就有更多的C的功能。于是,从此之后就用现有的编译器解释更复杂的语言,用更复杂的语言写出更好的编译器,然后不断这样迭代。这确实是编译器的演变。
然后最后一个问题就是当一个新的CPU发明过后,怎么办,需要重写又从汇编开始写编译器吗?答案是不用。假设你有一个CPU A执行一些代码,你用汇编写了一个基础的C编译器,然后用C写出了更复杂的编译器,接受更复杂的C功能,然后不断循环演化。现在你有了CPU B,CPU B和CPU A执行两套完全不同的代码,那如何让CPU B的机器也可以变异C语言呢?因为现在A上面已经可以运行非常复杂的C语言程序了,所以你可以在A上面开发一个编译器把C语言程序转化为CPU B的执行代码。然后用这个程序,直接编译你的C语言编译器,再把这个程序转换到有B命令集的电脑上面,这样你就开发出了B电脑需要的C语言编译器。
所以除非你真的是活在非常早起的人类。否在现在的编译器基本上都利用这种原理直接编译已经用C语言或者其它高级语言写好的代码来产生新的编译器就行了。理论上可以只使用C语言来开发C的编译器,不过处于一些历史原因和底层效率等因素的考量,部分代码还是使用汇编来实现的。
我举得不过是一个例子,不一定是真实的C语言编译的进化,何况有这么多不同的C语言编译器,每一个的发展历史都有小的不同。但是基本上都是利用了这种编译器编译新的编译器的思想来实现了。而这样回溯回去,最早的编译器只能使用汇编来些。而其实最早的汇编语言的编译器就只能使用机器语言来写了。不过都是先处理简单的转换任务,有了这个核心功能过后,就可以写程序转换更复杂的语法。然后越来越复杂。就有了各种各样的高级语言编译器了。
‘玖’ 编译器开发的四种技术
编译程序的开发常常采用这四种:自编译、交叉编译、自展和移植等技术实现。
‘拾’ 编译器的发展史
编译器
编译器,是将便于人编写,阅读,维护的高级计算机语言翻译为计算机能识别,运行的低级机器语言的程序。编译器将源程序(Source program)作为输入,翻译产生使用目标语言(Target language)的等价程序。源程序一般为高级语言(High-level language),如Pascal,C++等,而目标语言则是汇编语言或目标机器的目标代码(Object code),有时也称作机器代码(Machine code)。
一个现代编译器的主要工作流程如下:
源程序(source code)→预处理器(preprocessor)→编译器(compiler)→汇编程序(assembler)→目标程序(object code)→连接器(链接器,Linker)→可执行程序(executables)
目录 [隐藏]
1 工作原理
2 编译器种类
3 预处理器(preprocessor)
4 编译器前端(frontend)
5 编译器后端(backend)
6 编译语言与解释语言对比
7 历史
8 参见
工作原理
翻译是从源代码(通常为高级语言)到能直接被计算机或虚拟机执行的目标代码(通常为低级语言或机器言)。然而,也存在从低级语言到高级语言的编译器,这类编译器中用来从由高级语言生成的低级语言代码重新生成高级语言代码的又被叫做反编译器。也有从一种高级语言生成另一种高级语言的编译器,或者生成一种需要进一步处理的的中间代码的编译器(又叫级联)。
典型的编译器输出是由包含入口点的名字和地址以及外部调用(到不在这个目标文件中的函数调用)的机器代码所组成的目标文件。一组目标文件,不必是同一编译器产生,但使用的编译器必需采用同样的输出格式,可以链接在一起并生成可以由用户直接执行的可执行程序。
编译器种类
编译器可以生成用来在与编译器本身所在的计算机和操作系统(平台)相同的环境下运行的目标代码,这种编译器又叫做“本地”编译器。另外,编译器也可以生成用来在其它平台上运行的目标代码,这种编译器又叫做交叉编译器。交叉编译器在生成新的硬件平台时非常有用。“源码到源码编译器”是指用一种高级语言作为输入,输出也是高级语言的编译器。例如: 自动并行化编译器经常采用一种高级语言作为输入,转换其中的代码,并用并行代码注释对它进行注释(如OpenMP)或者用语言构造进行注释(如FORTRAN的DOALL指令)。
预处理器(preprocessor)
作用是通过代入预定义等程序段将源程序补充完整。
编译器前端(frontend)
前端主要负责解析(parse)输入的源程序,由词法分析器和语法分析器协同工作。词法分析器负责把源程序中的‘单词’(Token)找出来,语法分析器把这些分散的单词按预先定义好的语法组装成有意义的表达式,语句 ,函数等等。 例如“a = b + c;”前端词法分析器看到的是“a, =, b , +, c;”,语法分析器按定义的语法,先把他们组装成表达式“b + c”,再组装成“a = b + c”的语句。 前端还负责语义(semantic checking)的检查,例如检测参与运算的变量是否是同一类型的,简单的错误处理。最终的结果常常是一个抽象的语法树(abstract syntax tree,或 AST),这样后端可以在此基础上进一步优化,处理。
编译器后端(backend)
编译器后端主要负责分析,优化中间代码(Intermediate representation)以及生成机器代码(Code Generation)。
一般说来所有的编译器分析,优化,变型都可以分成两大类: 函数内(intraproceral)还是函数之间(interproceral)进行。很明显,函数间的分析,优化更准确,但需要更长的时间来完成。
编译器分析(compiler analysis)的对象是前端生成并传递过来的中间代码,现代的优化型编译器(optimizing compiler)常常用好几种层次的中间代码来表示程序,高层的中间代码(high level IR)接近输入的源程序的格式,与输入语言相关(language dependent),包含更多的全局性的信息,和源程序的结构;中层的中间代码(middle level IR)与输入语言无关,低层的中间代码(Low level IR)与机器语言类似。 不同的分析,优化发生在最适合的那一层中间代码上。
常见的编译分析有函数调用树(call tree),控制流程图(Control flow graph),以及在此基础上的 变量定义-使用,使用-定义链(define-use/use-define or u-d/d-u chain),变量别名分析(alias analysis),指针分析(pointer analysis),数据依赖分析(data dependence analysis)等等。
上述的程序分析结果是编译器优化(compiler optimization)和程序变形(compiler transformation)的前提条件。常见的优化和变新有:函数内嵌(inlining),无用代码删除(Dead code elimination),标准化循环结构(loop normalization),循环体展开(loop unrolling),循环体合并,分裂(loop fusion,loop fission),数组填充(array padding),等等。 优化和变形的目的是减少代码的长度,提高内存(memory),缓存(cache)的使用率,减少读写磁盘,访问网络数据的频率。更高级的优化甚至可以把序列化的代码(serial code)变成并行运算,多线程的代码(parallelized,multi-threaded code)。
机器代码的生成是优化变型后的中间代码转换成机器指令的过程。现代编译器主要采用生成汇编代码(assembly code)的策略,而不直接生成二进制的目标代码(binary object code)。即使在代码生成阶段,高级编译器仍然要做很多分析,优化,变形的工作。例如如何分配寄存器(register allocatioin),如何选择合适的机器指令(instruction selection),如何合并几句代码成一句等等。
编译语言与解释语言对比
许多人将高级程序语言分为两类: 编译型语言 和 解释型语言 。然而,实际上,这些语言中的大多数既可用编译型实现也可用解释型实现,分类实际上反映的是那种语言常见的实现方式。(但是,某些解释型语言,很难用编译型实现。比如那些允许 在线代码更改 的解释型语言。)
历史
上世纪50年代,IBM的John Backus带领一个研究小组对FORTRAN语言及其编译器进行开发。但由于当时人们对编译理论了解不多,开发工作变得既复杂又艰苦。与此同时,Noam Chomsky开始了他对自然语言结构的研究。他的发现最终使得编译器的结构异常简单,甚至还带有了一些自动化。Chomsky的研究导致了根据语言文法的难易程度以及识别它们所需要的算法来对语言分类。正如现在所称的Chomsky架构(Chomsky Hierarchy),它包括了文法的四个层次:0型文法、1型文法、2型文法和3型文法,且其中的每一个都是其前者的特殊情况。2型文法(或上下文无关文法)被证明是程序设计语言中最有用的,而且今天它已代表着程序设计语言结构的标准方式。分析问题(parsing problem,用于上下文无关文法识别的有效算法)的研究是在60年代和70年代,它相当完善的解决了这个问题。现在它已是编译原理中的一个标准部分。
有限状态自动机(Finite Automaton)和正则表达式(Regular Expression)同上下文无关文法紧密相关,它们与Chomsky的3型文法相对应。对它们的研究与Chomsky的研究几乎同时开始,并且引出了表示程序设计语言的单词的符号方式。
人们接着又深化了生成有效目标代码的方法,这就是最初的编译器,它们被一直使用至今。人们通常将其称为优化技术(Optimization Technique),但因其从未真正地得到过被优化了的目标代码而仅仅改进了它的有效性,因此实际上应称作代码改进技术(Code Improvement Technique)。
当分析问题变得好懂起来时,人们就在开发程序上花费了很大的功夫来研究这一部分的编译器自动构造。这些程序最初被称为编译器的编译器(Compiler-compiler),但更确切地应称为分析程序生成器(Parser Generator),这是因为它们仅仅能够自动处理编译的一部分。这些程序中最着名的是Yacc(Yet Another Compiler-compiler),它是由Steve Johnson在1975年为Unix系统编写的。类似的,有限状态自动机的研究也发展了一种称为扫描程序生成器(Scanner Generator)的工具,Lex(与Yacc同时,由Mike Lesk为Unix系统开发)是这其中的佼佼者。
在70年代后期和80年代早期,大量的项目都贯注于编译器其它部分的生成自动化,这其中就包括了代码生成。这些尝试并未取得多少成功,这大概是因为操作太复杂而人们又对其不甚了解。
编译器设计最近的发展包括:首先,编译器包括了更加复杂算法的应用程序它用于推断或简化程序中的信息;这又与更为复杂的程序设计语言的发展结合在一起。其中典型的有用于函数语言编译的Hindley-Milner类型检查的统一算法。其次,编译器已越来越成为基于窗口的交互开发环境(Interactive Development Environment,IDE)的一部分,它包括了编辑器、连接程序、调试程序以及项目管理程序。这样的IDE标准并没有多少,但是对标准的窗口环境进行开发已成为方向。另一方面,尽管近年来在编译原理领域进行了大量的研究,但是基本的编译器设计原理在近20年中都没有多大的改变,它现在正迅速地成为计算机科学课程中的中心环节。
在九十年代,作为GNU项目或其它开放源代码项目的一部分,许多免费编译器和编译器开发工具被开发出来。这些工具可用来编译所有的计算机程序语言。它们中的一些项目被认为是高质量的,而且对现代编译理论感性趣的人可以很容易的得到它们的免费源代码。
大约在1999年,SGI公布了他们的一个工业化的并行化优化编译器Pro64的源代码,后被全世界多个编译器研究小组用来做研究平台,并命名为Open64。Open64的设计结构好,分析优化全面,是编译器高级研究的理想平台。
编译器是一种特殊的程序,它可以把以特定编程语言写成的程序变为机器可以运行的机器码。我们把一个程序写好,这时我们利用的环境是文本编辑器。这时我程序把程序称为源程序。在此以后程序员可以运行相应的编译器,通过指定需要编译的文件的名称就可以把相应的源文件(通过一个复杂的过程)转化为机器码了。
编译器工作方法
首先编译器进行语法分析,也就是要把那些字符串分离出来。然后进行语义分析,就是把各个由语法分析分析出的语法单元的意义搞清楚。最后生成的是目标文件,我们也称为obj文件。再经过链接器的链接就可以生成最后的可执行代码了。有些时候我们需要把多个文件产生的目标文件进行链接,产生最后的代码。我们把一过程称为交叉链接。