对于一些不遵照 POJ(JVM 里的 Pascal)的人来讲,它是一个编译器,将子集从 Pascal 转换成 JASM(Java 程序集),便于我们可以使用JVM 做为实行环境。
在上一篇文章中,大家在错误捕捉、对 string 类别的关系运算符的支持以及界定(与使用)Pascal 过程.
的概率方面进行了一些改善在出版物中,我们将介绍对 Pascal 函数(functions)的支持。不久后大家就能完成该项目的最后一个目标:从标准输入中载入一个数字并计算其阶乘。
在我们为JVM 开展编译时,必须详细描述这一令人难以置信的虚拟机的每个点作用。因而,我多次详解JVM 的结构原理以及它的一些命令(操作码)。
适用 Pascal 函数(函数)到现在为止,我们有一种方法来定义和启用 Pascal 的过程。此后 PR 中还能够定义和启用 Pascal 的函数.
在此提交中,实现了一个Java 程序去了解JVM 怎样处理定义和调用函数。来自下边的Java程序:
公共类FunctionCall{
公共静态失效主(字符串[] args){
System.out.println("来自main的您好!");
System.out.println(myMethod());
}
静态字符串myMethod(){
回到“来自 myMethod 的您好!
}
}
在我们反汇编类时,我们得到下列程序集:
1:公共类 FunctionCall {
2:公共静态主([java/lang/String)V{
3:getstaticjava/lang/System.outjava/io/PrintStream
4:ldc“主站你好!”
5:启用虚似java/io/PrintStream.println(java/lang/String)V
6:
7:getstaticjava/lang/System.outjava/io/PrintStream
8:invokestatic FunctionCall.myMethod()java/lang/String
9:启用虚似java/io/PrintStream.println(java/lang/String)V
10:
11:回到
12:}
13:
14:静态 myMethod()java/lang/String {
15:ldc“我的方法您好!”
16:
17:回到
18:}
19:}
根据这个例子,可以知道:
为了调用方法,JVM 应用命令“invokestatic FunctionCall.myMethod()java/lang/String”(第 8 行),其中: invokestatic 是接受要调用的方式的完整签字做为参数命令; FunctionCall 是类名字; myMethod()java/lang/String 是方式的完整签字以及参数(在本例中为无)和返回类型(在本例中向 java/lang/String);命令areturn(第17行)停止函数并把回到字符串留到堆栈上。换句话说,来自下边的 Pascal 程序:
程序function_call_wo_params;
函数 myfunction :字符串;
逐渐
myfunction:=来自 myfunction 的问候!;
末尾;
逐渐
writeln(来自源程序的您好!);
writeln(myfunction());
末尾。
POJ已调节形成下列 JASM:
// POJ0.1产生的编码
公共类function_call_wo_params{
;;函数 myfunction :字符串;
静态myfunction()java/lang/String{
ldc“我函数您好!”
贮存 100 ;;第 100 位储存函数的返回值
载入 100 ;;堆栈函数返回值
收益 ;;留有“来自我功能的您好!”在堆栈中
}
;;关键程序(关键)
公共静态主([java / lang / String)V{
;;writeln(来自源程序的您好!);
getstaticjava/lang/System.outjava/io/PrintStream
ldc“主站你好!”
invokevirtualjava/io/PrintStream.print(java/lang/String)V
getstaticjava/lang/System.outjava/io/PrintStream
启用虚似java/io/PrintStream.println()V
;;writeln(myfunction());
getstaticjava/lang/System.outjava/io/PrintStream
invokestaticfunction_call_wo_params.myfunction()java/lang/String
invokevirtualjava/io/PrintStream.print(java/lang/String)V
getstaticjava/lang/System.outjava/io/PrintStream
启用虚似java/io/PrintStream.println()V
回到
}
}
最细心的人一定察觉到了上边的“astore 100”并想:
为何要把函数返回值存储在局部变量中?这是因为在 Pascal 中,函数的返回值在函数执行期间能设 N 次,但我们在JVM 中只有堆栈一次结论;为何排在第100位?函数或流程的局部变量从部位 0 逐渐,因而任意选择部位 100 来存储返回值;可是能否进行改善,确保在本例中仅形成命令ldc“Hello from myfunction!”,随后形成命令areturn?没错,没错,可是 POJ没有实现市场编译器中出现的提升环节,这可能在未来完成。此递交完成了对符号表里的“function”种类和解析器的支持。
在上面的示例中,函数没有参数。在此提交中,完成了含有参数函数的预期成果。根据下边的 Pascal 程序:
程序 function_call_with_two_params;
函数 addvalues(value1, value2: 整数) : 整数;
逐渐
加上值:=值1+值2;
末尾;
逐渐
writeln(2+4=,addvalues(2,4));
末尾。
POJ恰当生成了下列 JASM:
// POJ0.1产生的编码
公共类 function_call_with_two_params{
;;函数 addvalues(value1, value2: 整数) : 整数;
静态加值(I,I)I{
;;加上值:=值1+值2;
载入0
载入1
我加
这是100
载入100
回到
}
;;关键程序
公共静态主([java / lang / String)V{
;;writeln(2+4=,...);
getstaticjava/lang/System.outjava/io/PrintStream
LDC“2+4=”
invokevirtualjava/io/PrintStream.print(java/lang/String)V
getstaticjava/lang/System.outjava/io/PrintStream
;;这儿代码启用addvalues(2,4)
西普什2
西普什4
invokestatic function_call_with_two_params.addvalues(I,I)I
;;这儿代码启用 writeln 并返回addvalues
启用虚似java/io/PrintStream.print(I)V
getstaticjava/lang/System.outjava/io/PrintStream
启用虚似java/io/PrintStream.println()V
回到
}
}
下一步在下一篇文章中,我们将探讨前后文、发觉错误、嵌入语句、数据输入,并总结该项目的最后一个目标:递归计算阶乘。
完备的项目代码包括项目详细代码和文档的存储库在这儿。
以上就是适用 Pascal 函数的详细内容,大量请关注其他类似文章!