① 编程程序是怎么实现的
编程的话,我的语言描述就是,
要编一个程序,那么这个程序有它的基本语言。就像我们学习说话,先学会发音,然后组织语言;
学会了基本的语言后,我们就根据需要来编程,在编程过程当中,我们要考虑各种情况,使程序实现我们需要,如果考虑不周到,就会有漏洞,需要补上。所以在编程当中,用到最多的语言就是(如果,或者)这样的词汇。
把各种漏洞都堵上了,电脑执行你的指令,不管你有没有提到其它方面,所有的程序它都要复核一边。所以程序不要太庞大,需要简洁,减少电脑的运行。这个就与你堵漏洞有相反的要求。如果你编写了一个子程序,程序经常要用到这个,那么你要考虑怎么把这个程序精简到最低程度。
因为电脑只能识别这个语言,所以不能够在语法上有错误,它会理解不了。
说到漏洞,比如说,记事本里面查找功能,你要找文字(J3),那么它把(J33),(J32)里面的也找了,如果你在里面替换什么内容的话,就会出现问题。这个问题就是你要考虑的,怎么把漏洞堵上,不发生这样的问题。
所以我认为编程就是你对这个程序的理解程度考验。至于基本语言你学会就好,你要做的就是把你想说的话,翻译成电脑能够听懂的话。要说明,什么不能够做,什么应当做,一一交代清楚,只要说漏了一句,电脑就不按你的思路走了。(电脑不会思考,你要做的就是让电脑按你的思路走。)
② C语言文件的编译与执行的四个阶段并分别描述
开发C程序有四个步骤:编辑、编译、连接和运行。
任何一个体系结构处理器上都可以使用C语言程序,只要该体系结构处理器有相应的C语言编译器和库,那么C源代码就可以编译并连接到目标二进制文件上运行。
1、预处理:导入源程序并保存(C文件)。
2、编译:将源程序转换为目标文件(Obj文件)。
3、链接:将目标文件生成为可执行文件(EXE文件)。
4、运行:执行,获取运行结果的EXE文件。
(2)早期编译程序是如何开发的扩展阅读:
将C语言代码分为程序的几个阶段:
1、首先,源代码文件测试。以及相关的头文件,比如stdio。H、由预处理器CPP预处理为.I文件。预编译的。文件不包含任何宏定义,因为所有宏都已展开,并且包含的文件已插入。我归档。
2、编译过程是对预处理文件进行词法分析、语法分析、语义分析和优化,生成相应的汇编代码文件。这个过程往往是整个程序的核心部分,也是最复杂的部分之一。
3、汇编程序不直接输出可执行文件,而是输出目标文件。汇编程序可以调用LD来生成可以运行的可执行程序。也就是说,您需要链接大量的文件才能获得“a.out”,即最终的可执行文件。
4、在链接过程中,需要重新调整其他目标文件中定义的函数调用指令,而其他目标文件中定义的变量也存在同样的问题。
③ 最早的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语言编译器,每一个的发展历史都有小的不同。但是基本上都是利用了这种编译器编译新的编译器的思想来实现了。而这样回溯回去,最早的编译器只能使用汇编来些。而其实最早的汇编语言的编译器就只能使用机器语言来写了。不过都是先处理简单的转换任务,有了这个核心功能过后,就可以写程序转换更复杂的语法。然后越来越复杂。就有了各种各样的高级语言编译器了。
④ 开发一个c语言程序要经过哪四个步骤
开发一个C语言程序需要经过的四个步骤:编辑、编译、连接、运行。
C语言程序可以使用在任意架构的处理器上,只要那种架构的处理器具有对应的培羡纤C语言编译器和库,然后将C源代码编配仿译、连接成目标二进制文件之后即可运行。
1、预处理:输入源程序并保存(.C文件)。
2、编译:将源程序翻译为目标文件(.OBJ文件)。
3、链接:将目标文件生成可执行文件(.EXE文件)。
4、运行:执行.EXE文件,得到运行结果。
(4)早期编译程序是如何开发的扩展阅读:
C语言代码变为程序的几个阶段:
1、首先是源代码文件test.c和相关的头文件,如stdio.h等被预处理器cpp预处理成一个.i文件。经过预编译后的.i文件不包含任何宏定义,因为所有的宏已经被展开,并且包含的文件也已经被插入到.i文件中。
2、编译过程就是把预处理完的文件进行一系列的词法分析、语法分析、语义分析以及优化后产生相应的汇编代码文件,这个过程往往是我们所说的整个程序的构建的核心部分,也是最复杂的部分之一。派胡
3、汇编器不直接输出可执行文件而是输出一个目标文件,汇编器可以调用ld产生一个能够运行的可执行程序。即需要将一大堆文件链接起来才可以得到“a.out”,即最终的可执行文件。
4、在链接过程中,对其他定义在目标文件中的函数调用的指令需要被重新调整,对实用其他定义在其他目标文件的变量来说,也存在同样问题。
参考资料来源:网络-c语言
⑤ 世界上第一个语言编译程序是用什么语言编写的
数字电子计算机,在1946年诞生,那时还没有编译程序,一台计算机就是一个程序,修改程序,就是直接修该内存的指令(电路).后来,出现了汇编程序(当然用机器语言写的),汇编语言就出现了,在后来就有了高级语言.至于第一个编译程序,严格来说汇编程序也是编译程序,所以是用机器语言写的.
⑥ 程序开发的四个步骤
1、定义程序目标。在开始写程序之前,应对希望程序要做什么有一个清晰的想法。考虑程序需要的信息,程序需要进行的计算和操作,以及程序应该向你报告的信息。在这一规划阶老液段,应该用一般概念来考虑问题,而不是一些具体的计算机语言术语来考虑。
2、设计程序。在对程序需要完成的事情有一个概念性的认识后,就应该决定程序要如何完成它,用户界面应该是怎么样的,程序应该如何组织,目标用户是谁,有多长的时间来完成实现这个程序等等。
3、编写代码。在程序有了清晰的设计后,就可以通过编写代码来实现它了。也就是说,将设计构思转变为C语言。一般来说,需要使用文本编辑器来创建一种称为源代码的文件,该文件包含程序设计的C实现形式。
4、编译源代码。编译细节取决于编程环境,编译器还检查程序是否为有效的C语言程序。
5、运行程序。一般来说,可执行文件就是打开之后可以直接能够运行的文件。
6、测试和调试程序。程序能够正常运行那是极好的,但有时候它也可能运行不正确。因此,应该进行检查,看程序是否存在错误。姿睁
7、维护和修改程序。在为自己或为别人迹含岁创建程序后,该程序可能会有更广泛的应用。如果是这样,可能会发现需要对其进行更改,也就是项目的维护和修改。
⑦ 请问编写软件的第一个语言程序是如何诞生的
早期的计算机软件都是用汇编语言直接编写的,这种状况持续了数年。当人们发现为不同类型的CPU编写可重用软件的开销要明显高于编写编译器时,人们发明了高级编程语言。由于早期的计算机的内存很少,当大家实现编译器时,遇到了许多技术难题。
大约在20世纪50年代末期,与机器无关的编程语言被首次提出。随后,人们开发了几种实验性质的编译器。第一个编译器是由Grace Hopper于1952年为A-0语言编写的。通常认为,1957年由IBM的约翰·巴科斯领导的FORTRAN团队介绍了第一个完整的编译器。1960年,COBOL成为一种较早的能在多种架构下被编译的语言。
高级语言在许多领域流行起来。由于新的编程语言支持的功能越来越多,计算机的架构越来越复杂,这使得编译器也越来越复杂。
早期的编译器是用汇编语言编写的。首个能编译自己源程序的编译器是在1962年由麻省理工学院的Hart和Levin制作的。从20世纪70年代起,实现能编译自己源程序的编译器变得越来越可行,不过还是用Pascal和C语言来实现编译器更加流行。制作某种语言的第一个能编译器,要么需要用其它语言来编写,要么就像Hart和Levin制作Lisp编译器那样,用解释器来运行编译器。
引自 : 维基网络
⑧ 谁能简单阐述下java编译执行的过程
Java虚拟机(JVM)是可运行Java代码的假想计算机。
只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该系统上运行。
本文首先简要介绍从Java文件的编译到最终执行的过程,随后对JVM规格描述作一说明。
一.Java源文件的编译、下载、解释和执行
Java应用程序的开发周期包括编译、下载、解释和执行几个部分。
Java编译程序将Java源程序翻译为JVM可执行代码?字节码。
这一编译过程同C/C++的编译有些不同。
当C编译器编译生成一个对象的代码时,该代码是为在某一特定硬件平台运行而产生的。
因此,在编译过程中,编译程序通过查表将所有对符号的引用转换为特定的内存偏移量,以保证程序运行。
Java编译器却不将对变量和方法的引用编译为数值引用,也不确定程序执行过程中的内存布局,而是将这些符号引用信息保留在字节码中,由解释器在运行过程中创立内存布局,然后再通过查表来确定一个方法所在的地址。
这样就有效的保证了Java的可移植性和安全性。
运行JVM字节码的工作是由解释器来完成的。
解释执行过程分三部进行:代码的装入、代码的校验和代码的执行。
装入代码的工作由"类装载器"(classloader)完成。
类装载器负责装入运行一个程序需要的所有代码,这也包括程序代码中的类所继承的类和被其调用的类。
当类装载器装入一个类时,该类被放在自己的名字空间中。
除了通过符号引用自己名字空间以外的类,类之间没有其他办法可以影响其他类。
在本台计算机上的所有类都在同一地址空间内,而所有从外部引进的类,都有一个自己独立的名字空间。
这使得本地类通过共享相同的名字空间获得较高的运行效率,同时又保证它们与从外部引进的类不会相互影响。
当装入了运行程序需要的所有类后,解释器便可确定整个可执行程序的内存布局。
解释器为符号引用同特定的地址空间建立对应关系及查询表。
通过在这一阶段确定代码的内存布局,Java很好地解决了由超类改变而使子类崩溃的问题,同时也防止了代码对地址的非法访问。
随后,被装入的代码由字节码校验器进行检查。
校验器可发现操作数栈溢出,非法数据类型转化等多种错误。
通过校验后,代码便开始执行了。
Java字节码的执行有两种方式:
1.即时编译方式:解释器先将字节码编译成机器码,然后再执行该机器码。
2.解释执行方式:解释器通过每次解释并执行一小段代码来完成Java字节码程序的所有操作。
通常采用的是第二种方法。
由于JVM规格描述具有足够的灵活性,这使得将字节码翻译为机器代码的工作
具有较高的效率。
对于那些对运行速度要求较高的应用程序,解释器可将Java字节码即时编译为机器码,从而很好地保证了Java代码的可移植性和高性能。
二.JVM规格描述
JVM的设计目标是提供一个基于抽象规格描述的计算机模型,为解释程序开发人员提很好的灵活性,同时也确保Java代码可在符合该规范的任何系统上运行。
JVM对其实现的某些方面给出了具体的定义,特别是对Java可执行代码,即字节码(Bytecode)的格式给出了明确的规格。
这一规格包括操作码和操作数的语法和数值、标识符的数值表示方式、以及Java类文件中的Java对象、常量缓冲池在JVM的存储映象。
这些定义为JVM解释器开发人员提供了所需的信息和开发环境。
Java的设计者希望给开发人员以随心所欲使用Java的自由。
JVM定义了控制Java代码解释执行和具体实现的五种规格,它们是:
JVM指令系统
JVM寄存器
JVM栈结构
JVM碎片回收堆
JVM存储区
2.1JVM指令系统
JVM指令系统同其他计算机的指令系统极其相似。
Java指令也是由操作码和操作数两部分组成。
操作码为8位二进制数,操作数进紧随在操作码的后面,其长度根据需要而不同。
操作码用于指定一条指令操作的性质(在这里我们采用汇编符号的形式进行说明),如iload表示从存储器中装入一个整数,anewarray表示为一个新数组分配空间,iand表示两个整数的"与",ret用于流程控制,表示从对某一方法的调用中返回。
当长度大于8位时,操作数被分为两个以上字节存放。
JVM采用了"bigendian"的编码方式来处理这种情况,即高位bits存放在低字节中。
这同Motorola及其他的RISCCPU采用的编码方式是一致的,而与Intel采用的"littleendian"的编码方式即低位bits存放在低位字节的方法不同。
Java指令系统是以Java语言的实现为目的设计的,其中包含了用于调用方法和监视多先程系统的指令。
Java的8位操作码的长度使得JVM最多有256种指令,目前已使用了160多种操作码。
2.2JVM指令系统
所有的CPU均包含用于保存系统状态和处理器所需信息的寄存器组。
如果虚拟机定义较多的寄存器,便可以从中得到更多的信息而不必对栈或内存进行访问,这有利于提高运行速度。
然而,如果虚拟机中的寄存器比实际CPU的寄存器多,在实现虚拟机时就会占用处理器大量的时间来用常规存储器模拟寄存器,这反而会降低虚拟机的效率。
针对这种情况,JVM只设置了4个最为常用的寄存器。
它们是:
pc程序计数器
optop操作数栈顶指针
frame当前执行环境指针
vars指向当前执行环境中第一个局部变量的指针
所有寄存器均为32位。
pc用于记录程序的执行。
optop,frame和vars用于记录指向Java栈区的指针。
2.3JVM栈结构
作为基于栈结构的计算机,Java栈是JVM存储信息的主要方法。
当JVM得到一个Java字节码应用程序后,便为该代码中一个类的每一个方法创建一个栈框架,以保存该方法的状态信息。
每个栈框架包括以下三类信息:
局部变量
执行环境
操作数栈
局部变量用于存储一个类的方法中所用到的局部变量。
vars寄存器指向该变量表中的第一个局部变量。
执行环境用于保存解释器对Java字节码进行解释过程中所需的信息。
它们是:上次调用的方法、局部变量指针和操作数栈的栈顶和栈底指针。
执行环境是一个执行一个方法的控制中心。
例如:如果解释器要执行iadd(整数加法),首先要从frame寄存器中找到当前执行环境,而后便从执行环境中找到操作数栈,从栈顶弹出两个整数进行加法运算,最后将结果压入栈顶。
操作数栈用于存储运算所需操作数及运算的结果。
2.4JVM碎片回收堆
Java类的实例所需的存储空间是在堆上分配的。
解释器具体承担为类实例分配空间的工作。
解释器在为一个实例分配完存储空间后,便开始记录对该实例所占用的内存区域的使用。
一旦对象使用完毕,便将其回收到堆中。
在Java语言中,除了new语句外没有其他方法为一对象申请和释放内存。
对内存进行释放和回收的工作是由Java运行系统承担的。
这允许Java运行系统的设计者自己决定碎片回收的方法。
在SUN公司开发的Java解释器和HotJava环境中,碎片回收用后台线程的方式来执行。
这不但为运行系统提供了良好的性能,而且使程序设计人员摆脱了自己控制内存使用的风险。
2.5JVM存储区
JVM有两类存储区:常量缓冲池和方法区。
常量缓冲池用于存储类名称、方法和字段名称以及串常量。
方法区则用于存储Java方法的字节码。
对于这两种存储区域具体实现方式在JVM规格中没有明确规定。
这使得Java应用程序的存储布局必须在运行过程中确定,依赖于具体平台的实现方式。
JVM是为Java字节码定义的一种独立于具体平台的规格描述,是Java平 *** 立性的基础。
目前的JVM还存在一些限制和不足,有待于进一步的完善,但无论如何,JVM的思想是成功的。
对比分析:如果把Java原程序想象成我们的C++原程序,Java原程序编译后生成的字节码就相当于C++原程序编译后的80x86的机器码(二进制程序文件),JVM虚拟机相当于80x86计算机系统,Java解释器相当于80x86CPU。
在80x86CPU上运行的是机器码,在Java解释器上运行的是Java字节码。
Java解释器相当于运行Java字节码的“CPU”,但该“CPU”不是通过硬件实现的,而是用软件实现的。
Java解释器实际上就是特定的平台下的一个应用程序。
只要实现了特定平台下的解释器程序,Java字节码就能通过解释器程序在该平台下运行,这是Java跨平台的根本。
当前,并不是在所有的平台下都有相应Java解释器程序,这也是Java并不能在所有的平台下都能运行的原因,它只能在已实现了Java解释器程序的平台下运行。
⑨ 编译器的历史
20世纪50年代,IBM的John Backus带领一个研究小组对FORTRAN语言及其编译器进行开发。但由于当时人们对编译理论了解不多,开发工作变得既复杂又艰苦。与此同时,Noam Chomsky开始了他对自然语言结构的研究。他的发现最终使得编译器的结构异常简单,甚至还带有了一些自动化。Chomsky的研究导致了根据语言文法的难易程度以及识别它们所需要的算法来对语言分类。正如Chomsky架构(Chomsky Hierarchy),它包括了文法的四个层次:0型文法、1型文法、2型文法和3型文法,且其中的每一个都是其前者的特殊情况。2型文法(或上下文无关文法)被证明是程序设计语言中最有用的,而且今天它已代表着程序设计语言结构的标准方式。分析问题(parsing problem,用于上下文无关文法识别的有效算法)的研究是在60年代和70年代,它相当完善的解决了这个问题。它已是编译原理中的一个标准部分。
有限状态自动机(Finite Automation)和正则表达式(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系统开发)是这其中的佼佼者。
在20世纪70年代后期和80年代早期,大量的项目都贯注于编译器其它部分的生成自动化,这其中就包括了代码生成。这些尝试并未取得多少成功,这大概是因为操作太复杂而人们又对其不甚了解。
编译器设计最近的发展包括:首先,编译器包括了更加复杂算法的应用程序它用于推断或简化程序中的信息;这又与更为复杂的程序设计语言的发展结合在一起。其中典型的有用于函数语言编译的Hindley-Milner类型检查的统一算法。其次,编译器已越来越成为基于窗口的交互开发环境(Interactive Development Environment,IDE)的一部分,它包括了编辑器、连接程序、调试程序以及项目管理程序。这样的IDE标准并没有多少,但是对标准的窗口环境进行开发已成为方向。另一方面,尽管在编译原理领域进行了大量的研究,但是基本的编译器设计原理在近20年中都没有多大的改变,它正迅速地成为计算机科学课程中的中心环节。
在20世纪90年代,作为GNU项目或其它开放源代码项目标一部分,许多免费编译器和编译器开发工具被开发出来。这些工具可用来编译所有的计算机程序语言。它们中的一些项目被认为是高质量的,而且对现代编译理论感兴趣的人可以很容易的得到它们的免费源代码。
大约在1999年,SGI公布了他们的一个工业化的并行化优化编译器Pro64的源代码,后被全世界多个编译器研究小组用来做研究平台,并命名为Open64。Open64的设计结构好,分析优化全面,是编译器高级研究的理想平台。
编译器相关专业术语: 1. compiler编译器;编译程序 2. on-line compiler 连线编译器 3. precompiler 预编译器 4. serial compiler 串行编译器 5. system-specific compiler 特殊系统编译器 6. Information Presentation Facility Compiler 信息展示设施编译器 7. Compiler Monitor System 编译器监视系统
⑩ 第一个 C 语言编译器是用什么语言编写的
第一个C语言编译器(简单的编译器)是用汇编完成的,后来的完整C语言编译器是用C语言编写的(也就是由简单的编译器编译)。