欢迎来到天天文库
浏览记录
ID:39637509
大小:128.00 KB
页数:4页
时间:2019-07-08
《关于编程语言的思考——编译型、解释型和虚拟机语言》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、我们知道,任何编程语言编写的程序归根到底都是由底层机器的机器代码(01序列)执行的,无论是编译型语言还是解释型语言。而任何高级编程语言程序的源代码都是一个字符序列,这个字符序列到底层的01序列是通过编译器或解析器经过多次转换完成的。图1编程语言的层次结构这个层次结构中,从高到低越来越接近于机器硬件。机器代码就是01序列,汇编语言就是描述本地机器的指令集体系结构,而高级语言就包含相应的数据结构和语法结构,更接近人类的语言习惯。因此,层次越高就越面向于人类。在计算机科学中,CPU被抽象为指令集体系结构,这个指令集描述了CPU所有完成的所有功能。所有的程序都经过编译或解释转化为这个指令集表示的机器程
2、序。在指令集中指令可以按功能划分为:1.数据传输指令,用于读写内存、寄存器。2.算术与逻辑运算指令,比如:addl执行双字(32bit)的加法,andl双字的按位与。3.控制流指令,用于实现高级编程语言中的分支、循环等控制结构。4.过程调用指令,用于实现函数调用,分配、恢复栈帧等操作。任何程序都需要被转换为某个指令集的指令序列,比如下列简单的求阶乘的C程序:1intfact_while(intn)2{3intresult=1;4while(n>1){5result*=n;6n=n-1;7}8returnresult;9}在32bit机器上,经过gcc编译之后的x86指令序列为:1movl8(%
3、ebp),%edx2movl$1,%eax3cmpl$1,%edx4jle.L75.L10:6imull%edx,%eax7subl$1,%edx1cmpl$1,%edx2jg.L103.L7:通过观察C程序的机器代码可以发现由C程序转化为机器代码,主要有数据类型和控制结构的转换。下面以x86指令集说明:1.数据类型的转换:在底层,x86指令对于数据是不区分逻辑类型的,也就是不分int,float,double。所有的数据按照其所占的字节数被归类为字(16个字节,Word)、双字(32个字节,DoubleWords)、四字(64个字节,QuadWords)。一个指令操作的数据类型是由这个指令的
4、后缀表示的,比如mov指令,movw操作字,movl操作双字。也就是说高级语言的程序中的不同数据类型反映到底层指令集上主要体现是指令的不同。比如,将上述C程序中的result类型改为short,在相应的汇编代码中的mov指令会由movl转换为movw。当然,还有一个问题就是C语言中的具体数据类型,在机器代码中是如何存储表示的。这应该是gcc编译器的职责,比如对于int,首先gcc需要知道底层指令集如何编码int,采用什么编码方式,字节顺序是Big-endian还是Little-endian等。在知道底层的实现方式后gcc才能将表示整型数字的字符串编码为相应的二进制形式。而对于数组、struct
5、和union这些数据结构会转化为相应的内存地址加偏移量的形式。2.控制结构的转换:控制结构就是执行指令的流程。在x86中,所有的指令集都是顺序执行。要实现分支、循环等结构,必须具备go形式的跳转指令,以及相应的条件判断指令。CPU中有一组条件码寄存器,指示算术或逻辑运算的状态(计算结果是否溢出、为0或者是负数等)。执行条件运算指令可以测试一个条件,比如"cmpl$1,%edx"比较直接数1与寄存器%edx中存放的数的大小,并将结果存入条件码寄存器中。接下来执行条件跳转指令,根据条件码寄存器中的状态进行判断是否进行跳转。比如“jg.L10”是在前一条的cmpl指令结果返回大于的情况跳转到L10,
6、否则执行下一条指令。当然,在进行函数调用时,还要在底层用机器码对其进行描述。我们知道,计算机科学中用栈来实现函数的调用(叫做调用栈),栈中存放栈帧。每一次函数调用对应一个栈帧,栈帧中包含该方法的局部变量、保存的寄存器值等数据。这样函数的调用和返回就对应着栈帧的入栈和出栈。CPU的寄存器组中,有两个专门用于实现方法调用,分别是%esp和%ebp。%esp是栈指针寄存器,存放当前函数栈栈顶的内存地址。%ebp是帧指针寄存器,在%esp和%ebp之间的内存地址序列就对应于当前函数的栈帧。由于函数调用、返回与栈帧的关系很密切,所以可以将以此函数调用过程描述为:1.初始化被调用函数的栈帧,并将其入栈。也
7、就是调用函数过程,通过call指令实现。2.执行被调用函数。3.恢复调用函数的栈帧,将被调用函数的栈帧出栈。也就是函数返回的过程,通过ret指令实现。对于初始化、恢复栈帧实际上都是%esp和%ebp的调整,还要包括传参和返回值的问题,这些都是由编译器实现的。上面介绍了C语言和机器语言的关系,下面看一下其他类型语言的实现机制。首先,我们可以把编程语言分为编译型语言、解释型语言和虚拟机语言。编译型语言
此文档下载收益归作者所有