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 等),但仍有些不同:

  1. 最主要不同是 JVM 的資料結構是一個稱為 Constant Pool table,在 .class 檔內用來描述 classes, function 以及 variables。
  2. 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."&lt;init&gt;"<img align="center" src="https://derjohng.doitwell.tw/wp-includes/images/yahoo/yahoo2.gif" class="wp-smiley" />)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<img align="center" src="https://derjohng.doitwell.tw/wp-includes/images/yahoo/yahoo2.gif" class="wp-smiley" />Ljava/lang/String<img align="center" src="https://derjohng.doitwell.tw/wp-includes/images/yahoo/yahoo3.gif" class="wp-smiley" />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 &lt;init&gt;()V
   aload_0
   invokenonvirtual java/lang/Object/&lt;init&gt;()V
   return
.end method

; specify the "main" method - this prints "Hello World"
.method public static main([Ljava/lang/String<img align="center" src="https://derjohng.doitwell.tw/wp-includes/images/yahoo/yahoo3.gif" class="wp-smiley" />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<img align="center" src="https://derjohng.doitwell.tw/wp-includes/images/yahoo/yahoo3.gif" class="wp-smiley" />V

    return
.end method

簡短的 Jasmin 使用說明,參考這裡 。

更仔細的說明,參考 The Java Virtual Machine Specification, Chapter 7 .

參考

  1. C Compiler Targeting the Java Virtual Machine 
  2. The Java Virtual Machine Specification 
  3. 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>"<img align="center" src="https://derjohng.doitwell.tw/wp-includes/images/yahoo/yahoo2.gif" class="wp-smiley" />)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>"<img align="center" src="https://derjohng.doitwell.tw/wp-includes/images/yahoo/yahoo2.gif" class="wp-smiley" />)V
   4:   aload_0
   5:   iconst_5
   6:   putfield        #2; //Field iii:I
   9:   return
</init>

所以,這些值是放在 <init>() 下,但 jasmin 下 .method public <init>()V 要自己產生,所以,要另外用 putfield 來給予啟始值了? !!昏頭!! 用 .field 的 assign 值不就沒意義了?




2 Responses to “Jasmin 筆記”

歡迎留言

敝站會審核留言的適宜性,您的留言可能會較晚發佈,而且小弟保留刪除的權利!!

站內搜尋



本站其他服務

本站其他軟體



  • 下一台單車(NextBike)

    打開定位即搜尋附近二十點自行車站點,不塞滿全部站點資料到整個地圖上,所以畫面簡潔方便看清楚目前所在地,若需要搜尋地圖其他位置附近站點,再點擊地圖即可。


  • 藝文快訊

    讓你可以輕鬆追蹤含有您想要關注關鍵詞的任何藝文活動訊息,只要有最新的資訊,「藝文快訊」即會推播通知給你.


  • 台灣空污警報(AirInfo)

    設定特定站點為推播通知關注點後,當該站點空氣品質變糟時,即時推播通知給您。另外提供站點附近基本天氣預測資料。


  • 油價快訊App (OilPrices)

    依據油價及匯率,估算台灣下週油價,另外提供三週、一年以及三年的歷史變化,以及週末下午推播通知最新油價預估或公告。


  • 臉書粉絲專頁搜尋 (FPSearch)

    不用登入臉書即可搜尋臉書粉絲專頁(臉書粉絲團)所公開的文章。您可以指定特定日期範圍之前的文章,也可設定搜尋粉絲專頁內包含特定關鍵詞的文章。


  • 照片去背(PhotoEraser)

    一款方便移除背景的工具,產生透明背景圖可以存回原本相簿,也可分享到其他 App 使用.