三 22 2010
中间语言
论坛 owiki 资助 QQ群1:12385000 QQ群2:56127995 Email:olanguage@126.com
如果你刚好要上网购买产品,你可以点击上淘宝购买支持O语言发展
———————————————————————————————————————–
O语言是一组支持中文的计算机语言套件,目前它包括了界面描述、中间语言、中文汇编及中文反汇编,并且拥有一个友好的开发环境。它是支持计算机最底层的二进制指令语言,为了便于学习和使用,中间语言的语法大量借鉴了C的语法格式,并且支持了C的标准库,因此可以说它是一个中文C,但也有与C明显不同的地方。比如指针的使用,在C中指针是用类型加星号表示,在中间语言中增加了一个地址类型用来表示指针,如果要表示地址类型可以类似这样 地址<整数> 整数变量; 以下详细介绍了中间语言……
什么是中间语言
中间语言是低级汇编语言的抽象,汇编语言是针对硬件开发的语言,它对硬件有高度的依赖性,一种汇编语言只能对一种硬件进行操作,而且是完全的操作。由于不同硬件架构的处理器之间的指令不能相互通用,但是在功能上又有很多一致的地方,都能对一定长度的二进制数进行各种运算操作,比如加法指令,在x86硬件系统中有,在MIPS硬件系统中也有,虽然具体的硬件实现上有所不同,指令的二进制代码也不同,但对人们而言作用是共同的,于是我们把这些相同的功能进行抽象,并制定相应的一套语法系统,让编译器能把一组相同的代码针对不同的硬件编译出不同的二进制代码,就开发出了当前的中间语言。概括地说中间语言是不同汇编语言的共同功能的抽象语法集。
中间语言与C语言有什么不同
一、在设计理念上有所不同
我们知道C语言是可以在不同硬件平台移植的,这里用了移植的概念,也就是说在最开始设计C语言的时候并没有考虑到所有硬件平台的问题,只是后来C语言流行以后,在不同平台上都按C语言的语法规范开发出了编译器,于是在一个平台上的代码可以直接拿到另一个平台上进行编译,这就有了移植的可能。而中间语言是直接在硬件上相同功能指令的抽象,不存在移植的问题,本身它实现的功能都是不同硬件所具有的功能。
二、在语法设计上有所不同
C语言的语法是以语句为单位的,一条语句会被编译成一条或多条汇编指令,以实现语句的功能。而中间语言是汇编语言的抽象,它以指令为单位的,一条中间语言的指令对应的简短的一条或几条相同功能的汇编指令。只是为了使用方便和编译器功能的增加,能够将多条中间语言的指令连起来写,表面上看起来有点类似于C语言的语句。
如何写注释文本
O中间语言的注释与C语言注释文本方式相同,行注释为两个英文右斜杠 // 块注释为 /* */
//这是行注释
/*这是块注释
…
*/
中间语言有哪些指令语句
一、运算指令
目前中间语言共实现了下列格式的指令
变量A = 变量B 赋值指令
变量A += 变量B 加法指令
变量A ++ 自加1指令
变量A -= 变量B 减法指令
变量A -- 自减1指令
变量A *= 变量B 乘法指令
变量A /= 变量B 除法指令
变量A %= 变量B 求模指令
变量A &= 变量B 与操作指令
变量A |= 变量B 或操作指令
变量A ^= 变量B 异或操作指令
变量A @= 变量B 取地址指令
变量A >>= 变量B 位右移指令
变量A <<= 变量B 位左移指令
变量A~ 求反指令
变量A <=> 变量B 互换指令
其中:
变量A可以是8位、16位和32位数据变量
变量B既可以是8位、16位和32位数据变量,也可以用立即数代替(除互换指令外),比如:
变量A += 0×1234
二、条件语句
下面介绍的条件语句中的<条件>可以是:
(变量A == 变量B)
(变量A != 变量B)
(变量A > 变量B)
(变量A < 变量B)
(变量A >= 变量B)
(变量A <= 变量B)
(变量A !> 变量B)
(变量A !< 变量B)
多个条件可以用 或者符号|| 并且符号&& 进行联接,比如:
(((变量A == 变量B) || (变量C > 变量D)) && (变量E <= 变量F))
如果语句
如果(<条件>)
{
//语句块
}
类似C/C++的if语句。
如果条件成立就执行语句块,也可以写成:
若(<条件>)
{
//语句块
}
否则如果语句
否则如果(<条件>)
{
//语句块
}
类似C/C++的else if语句。
如果条件成立就执行语句块,必须与前一个语句为“如果”语句或“否则如果”语句匹配使用,也可以写成:
又若(<条件>)
{
//语句块
}
否则语句
否则
{
//语句块
}
类似C/C++的else语句。
必须与前一个语句为如果语句或否则如果语句匹配使用,也可以写
成:
则
{
//语句块
}
循环语句
循环(<条件>)
{
//语句块
跳出; //break
继续; //continue
}
类似C/C++的while语句。
如果条件成立则执行{}中的代码,再判断条件,满足则继续执行语句块,直到不满足才跳出。循环中可以在任何地方使用“跳出;”来跳出循环(不管是否满足)。也可以使用“继续;”语句直接进入下一次条件判断。
执行…当语句
执行
{
//语句块
跳出; //break
继续; //continue
}当(<条件>)
类似C/C++的do…while语句。
与循环语句相似,只是判断条件在语句块之后,也就是说语句块至少会被执行一次。
设语句
设(语句1;<条件>;语句3)
{
//语句块
跳出; //break
继续; //continue
}
类似C/C++的for循环。
整数 i,j=0;
设(i=0;i<=100;i++)
{
j++;
}
i和j将循环100次
先执行语句1,再判断条件语句,满足,执行语句3,再执行{}中的语句,再判断(注意不再执行语句1),满足,继续……如此循环,直到不满足语句2为止。
三、标签与跳转语句
标签 标签A:
跳到 标签A;
跳到语句与C语言的goto语言作用相同,在函数内直接跳转到标签所定义的位置执行。
五、返回语句
函数可以有多个返回值,这必须在函数定:
有多个函数值时必须使用括号()
函数 函数名(整数32,整数32)=>(整数32,整数32,结构体名)
{
//函数体
返回(0×1234,变量A,结构A);
}
要接收返回值
如果只有一个返回值可以用
变量A = 函数名(1,2); 或者 函数名(1,2)=>变量A;
如果有多个返回值则必须用下列格式:
函数名(1,2)=>(变量A,变量B);
中间语言支持哪些数据类型
一、基本数据类型
O中间语言 对应C语言基本数据类型
整数8 char
正数8 unsigned char
整数16 short
正数16 unsigned short
整数32 int
正数32 unsigned int
小数32 float
小数64 double
基本的数据类型表示用这个这类型来定义一个变量时,这个变量长度为类型后面数据所指的长度,比如整数8表示定义的一个长度为8位变量,其它以此类推,而正数表示的是定义一个无符号数。
定义变量的格式是:类型名称 变量名;
举例:
整数32 变量A; //定义了一个类型为整数32的变量,变量名为“变量A”
无符号数是指变量的最高位不表示符号,而表示数据本身,比如一个8位的变量如果是有符号数,那么它真实的数值只有7位最高位表示符号位,而如果是无符号数,那么8位都表示的是数值。比如:11001100 这个二进制数
如果是有符号数则表示最高位是1表示是负的,真实的数值是1001100,那么这个数值就为:-52(以补码的形式计算而得)
如果是无符号的数则8位都是数值,其值为204
由此可得出:
整数8的取值范围是-128~+127,
正数8的取值范围是0~255
整数16的取值范围是-32768~32767
正数16 的取值范围是0~65535
整数32 的取值范围是-2147483648~2147483647
正数32 的取值范围是0~4294967295
二、地址类型
地址类型有两种,一种是变量地址,另一种是函数地址。地址类型变量的取值范围与正数32 相同,地址类型的变量可以与基本数据类型的变量一样使用进行各种运算。地址类型在C语言中被称作指针。
一个变量地址变量定义格式如下:
地址<变量类型> 地址变量名;
其中<变量类型>可以省略,则可以简单定义为:
地址 地址变量名;
如果地址变量在定义时有指定变量类型,,则可以使用:
取数值 地址变量名
来得到这个地址向指向的数据。
如果变量类型是下面所指出的复合数据类型,则可以使用:
地址变量名->成员名称
来对地址所指向的复合类型变量的成员进行操作。
一个函数地址变量定义格式如下:
函数类型 类型名(整数32 参数1,整数32 参数2)=>整数32;
类型名 函数变量;
当把函数变量赋值后,就可以把它当然一个函数来调用了:
函数变量(1,2);
三、复合数据类型(结构体、联合体、枚举体)
结构 结构体名
{
整数32 变量A;
整数32 变量B;
}
联合 联合体名
{
整数32 变量A;
整数32 变量B;
}
结构体与联合体的区别:
结构体的变量空间为所有子成员空间的总和,比如上面那个结构的变量空间为两个整数32长度相加为8个字节长度。
联合体的变量空间为最大子成员的变量空间,所有子成员共享这一空间,一个成员值改变可能会影响其它变量值的改变。比如上面那个联合体的变量空间是一个整数32的长度为4个字节。
枚举 枚举体名 //枚举体名可以省略
{
星期一;
星期二;
}
枚举体的成员不需要设置变量类型,只需要直接给出成员名称,所有的成员都默认为整数32类型。并且这些成员的变量可以直接使用,并被默认初始化为第一个成员为0,后一个成员的值为前一个成员自动增1,也可以用等号“=”对成员变量进行初始化赋值。
四、数据类型重定义
除了上面介绍的数据类型外,还可以对现有的数据类型名称进行重定义,其定义格式如下:
现有的类型名称 类定义 新的类型名称
举例:
整数32 类定义 自定义整数
读着 整数32 被类型重定义为 自定义整数
如何定义变量
一、全局变量
全局变量是被定义在函数外面的变量,全局变量的作用域是本文件内被定义之后的所有代码。下面的蓝色为全局变量A的作用域。
//全局变量定义
整数32 全局变量A;
函数 函数名()
{
……
}
……
//文件结束
二、局部变量
局部变量是被定义在函数内部的变量,局部变量的作用域是在语句块内,变量被定义之后。
函数 函数名()
{
//局部变量定义
整数32 局部变量A;
局部变量A = 1;
如果(局部变量A > 0)
{
整数32 局部变量B
//其它代码
……
}
……
//函数结束
}
上面蓝色(包括紫色部分)为局部变量A的作用域,紫色部分为局部变量B作用域。
三、外部变量
外部变量的定义与全局变量定义相同,只是在最前面加“外部的”关键字进行修饰。
外部的 整数32 变量A;
也可以在引用段中定义一个外部变量:
引用段
{
整数32 变量A;
}
外部变量只作用为变量引用而不在本文件中真实定义这么一个变量,这个变量必须在其它的文件中进行定义。
如何定义函数
一、自定义函数
定义函数以“函数”关键字开始,后面按顺序是函数调用类型、函数名、输入参数列表、返回类型列表,最后是函数体:
函数 [调用类型] 函数名(整数32 参数1,整数32参数2)=>(整数32,整数32)
{
//函数体
}
其中调用类型是可选项,指明函数被调用的类型,可以是O调用、C调用和标准调用,O调用与标准调用基本相同,只是多了对拥有多个返回值的处理。如果不写调用类型则默认为O调用。
C调用是参数从右到左压栈,调用者进行堆栈平衡
O调用与标准调用都是参数从右到左压栈,函数退出之前进行堆栈平衡。
如果函数没有返回值则不需要=>后面的内容
如果函数只有一个返回值则可以省略返回值列表的括号,直接=>返回类型
如果函数有多个返回值则必须要使用括号=>(多个返回值类型用逗号分格)。
如果函数有返回值类型,则在函数退出之前必须使用返回语句进行值返回。
二、入口函数
入口函数属于自定义函数,这个函数的关键字是“入口”而不是“函数”,这个函数不能拥有参数,程序将从这个函数开始执行。如:
入口 主函数()
{
}
一个程序只能拥有一个入口函数。
DLL程序的入口与这个有所不同,请参照“如何编写一个动态链接库程序”小节。
三、外部函数
外部函数是已经生成的只需要有函数定义就可以直接调用的函数,这个函数的函数体代码一般在库文件中。比如系统的API,C语言库及其它函数库。
要使用这样的函数必须在对函数进行定义,定义的格式与定义一般函数相同,只是不需要在函数体,并在最后加分号表示语句结束。并且外部函数与外部变量一样,必须用“外部的”关键字进行修饰,或者在引用段中定义。比如:
引用段
{
函数 获取模块句柄(整数32)=>整数32;
}
外部的 函数 画直线(整数32 x1,整数32 y1,整数32 x2 ,整数32 y2);
可以有参数名,也可以省略参数名。
你还必须在你的代码里添加对这个函数所在库的引用,引用库的语法格式如下:
.引用库<库名称>
中间语言关键字
.包含文 .引用库 引用段 外部的
宏定义 取消宏定义 类定义 取地址 取数值 取大小
入口 函数 结构 联合 枚举
如果 否则如果 否则 循环 跳出 继续 返回
若 又若 则 执行 当 设 标签 跳到
对于 若为 其它
C调用 标准调用 O调用
整数8 正数8
整数16 正数16
整数32 正数32
小数32
小数64
地址
函数类型
界面描述
