Jasmin 筆記 |
2008/01/11 ~ 阿亮 ~ |
現在做個簡單的 Compiler,包括三個部份,scanner 用 flex/scangen,parser 用 bison/yacc/llgen,剩下 code generation 可以直接輸出 assembly code 來做,也可輸出成 JVM bytecode。我之前沒學過 assembly code,直接學學這個也不錯,概念和 x86 差不多吧。
JVM 也屬 stack based machine platform (其他比如 PowerPC, x86, MIPS 等),但仍有些不同:
- 最主要不同是 JVM 的資料結構是一個稱為 Constant Pool table,在 .class 檔內用來描述 classes, function 以及 variables。
- JVM 禁止 memory reference,取得變數和函數方式會不同,而且沒有 global variables,要特別處理,比如要生成一個類別來處理 global variables.
若要參考 JVM Specification 來生成 binary 的 bytecode 當然很累,所以,有個現成的程式 Jasmin (即 JVM 的 assembler) 來使用,就比較方便了。
一般 .java 檔經 javac 轉成 .class (bytecode file)
public class HelloWorld { public static void main(String args[]) { System.out.println("Hello World!!"); } }
javap 用來 disassemble VM 指令,即可以知道一個 class 檔由哪些指令組成:
[derjohng@derjohngdediannao 551] $ javap -c HelloWorld Compiled from "HelloWorld.java" public class HelloWorld extends java.lang.Object{ public HelloWorld(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello World!! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return }
Jasmin 則是將 VM 指令寫成的檔案,轉成 bytecode file. 可視為 JVM 的一種 assembler,比如下面為 Jasmin 的指令例子(比如檔名為 HelloWord.j),執行 $jasmin HelloWord.j ,即會產生 HelloWord.class
.class public HelloWorld .super java/lang/Object ; specify the constructor method for the HelloWorld class .method public <init>()V aload_0 invokenonvirtual java/lang/Object/<init>()V return .end method ; specify the "main" method - this prints "Hello World" .method public static main([Ljava/lang/String;)V .limit stack 2 .limit locals 2 ; 將 output stream 和 string "Hello World!" 放到 stack. getstatic java/lang/System/out Ljava/io/PrintStream; ldc "Hello World!" invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V return .end method
簡短的 Jasmin 使用說明,參考這裡 。
更仔細的說明,參考 The Java Virtual Machine Specification, Chapter 7 .
參考
- C Compiler Targeting the Java Virtual Machine
- The Java Virtual Machine Specification
- Java Virtual Machine
2007.12.22 jasmin 產生的 class 檔案,用 java 執行,會有下述的 Error 出現
Exception in thread "main" java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file Main
Ans: 問題在於 method 內的 .limit stack 以及 .limit locals 一定要指定,這兩個值只能多給,不能少給。
2007.12.28 根據 Jasmin 手冊, .field 可以類似下面的用法:
.class public MyAda.Main .super java/lang/Object .field public XXX I = 20 .field public YYY D = 10.560000
但 jasmin 產生的 bytecode 用 javap -c 來看發現,其實並沒有給予起始值
Compiled from "Main.j" public class MyAda.Main extends java.lang.Object{ public int XXX; public double YYY; public MyAda.Main(); Code: 0: aload_0 1: invokespecial #46; //Method java/lang/Object."<init>":()V 4: return </init>
用下述的 java 檔,編成 class 檔
public class HelloWorld5 { public int iii=5;
會產生如下:
javap -c HelloWorld5 Compiled from "HelloWorld5.java" public class HelloWorld5 extends java.lang.Object{ public int iii; public HelloWorld5(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: aload_0 5: iconst_5 6: putfield #2; //Field iii:I 9: return </init>
所以,這些值是放在 <init>() 下,但 jasmin 下 .method public <init>
Thanks for this article.
I could solve some problems of jasmin by your help.
Best Regards
You are welcome.