Hatena::ブログ(Diary)

下目黒で Scala で x86_64アセンブラを勉強しつつコンパイラを作る日記

2008-01-31 JVMで動作するプログラミング言語を作るにはどうしたらよいのだろう

[]JVMで動作するプログラミング言語を作るにはどうしたらよいのだろう?(2)

とりあえず、JVM仕様勉強しないといけないっぽい。

本はあるようなのだけど、今は金欠なので本かわないで何とかしてみようと思う。

まず、JVMバイトコードの種類の一覧が欲しいと思う。

なにやらバイトコードバイトは命令が1バイトから来ているらしいので。

で、

http://www.asukaze.net/etc/cil/jvm_opcode.html

あすかぜさんというかたのサイトに一覧を見つけた。

この日本語訳も欲しいところなのだけど、まぁいいやと。


てことで、次にこれを試したいと思ったので、jasminとjasperを使って試してみる。

まず、試してみたのがiconst_1をiconst_0に変えるってこと。

javaバイトコードは小さい数は1バイトで済むとかいうことをjava3Dをやってた人のホームページ

見た覚えがある。

おそらく、iconst_1は1をスタックマシンpush

iconst_0は0をスタックマシンpushするという意味だろう。

ってことで、それを試すために、

a.java

class a {
  int n() { return 1; }
}

s.java

class s {
	public static void main(String[] argv) {
		System.out.println(new a().n());
	}
}

等というプログラムを作って

javac a.java
javac s.java

コンパイルする。

java s

とすれば、1と表示された。

java -jar jasper.jar a.class 

でa.jというファイルにディスアセンブルしてみると以下のようになった。

.source                  a.java
.class                   a
.super                   java/lang/Object


.method                  <init>()V
   .limit stack          1
   .limit locals         1
   .line                 1
   aload_0               
   invokespecial         java/lang/Object/<init>()V
   return                
.end method              

.method                  n()I
   .limit stack          1
   .limit locals         1
   .line                 3
   iconst_1              
   ireturn               
.end method              

なんだかよく分からないけどとりあえず、出来たプログラムをjasminでアセンブルする。

java -jar jasmin.jar a.j

で、a.class再生成される。

この後、

java s

で実行すると1と表示される。うまく行っているようだ。

さて、この中で一番下の

   iconst_1              
   ireturn               

ここが今回注目のiconst_1です。これをiconst_0に変えて

java -jar jasmin.jar a.j
java s

として、コンパイル実行すると0と表示された成功だぁ!iconst_5まであるので、iconst_5とやってみると5と表示される。

さて、今a.classは226 バイトです。ここで、iconst_n以外のものを使ってみましょう。

a.java

class a {
  int n() { return 33; }
}

とかして、コンパイル後、jasperでディスアセンブルすると、iconst_1だった部分が

  bipush 33

となってました。どうも、bipushがintの値をスタックに積む命令のようです。

ということで、iconst_1の部分をbipush 33にして、アセンブルしなおすと、227バイトになりました。

1バイトしか増えてませんね。bipushは1バイトだけ余分に食うんですね。

てことは、sipushとかいうのだと2バイトとかあるんじゃなかろうかとやってみると、ありました。

バイトコード表にも載ってます。で、228バイトと2バイト増えました。

では4バイトだと、iipushとかlipushかなぁ思って見ますがありません。ムムム。

ではと、a.javaにreturn 3333333とか書いて、jasperでディスアセンブルしてみると。

   ldc                   333333

となってました。ldcか。ldcがどうやら、4バイトのものらしいです。232バイトなので4バイト増えてる。

間違いない。ということで、今日はintをスタックpushする命令を複数個試してみたのでした。

SiroKuroSiroKuro 2008/02/01 11:13 jvm では int などの 4byte 値はコンスタントプールエントリに保持することになりますので、コンスタントプールエントリからロードする命令 ldc(LoadConstant) を使ってロードすることになります。ldc を使うとコンスタントプールに入っている int, float, String が push できます。ちなみに ldc2_w 命令だと long や double が push できますよ。

h_sakuraih_sakurai 2008/02/01 15:05 ldcはコンスタントプールからのロードってのは、気がついてたのだけど修正する前にコメントされてしまったのでした。

くろくろ 2008/02/07 16:42 お忙しいなかすいません、javascriptで演算子構文解析を使った構文解析器をやってくれませんか??

くろくろ 2008/02/07 16:42 お忙しいなかすいません、javascriptで演算子構文解析を使った構文解析器をやってくれませんか??