海野秀之(うんのひでゆき)の外部記憶
Twitter (twilog) / RSS / アンテナ / ぶくま
そろそろ出来てきたので、というか、今年中に動かすのが目標だったので、ちょっと無理やりにでも動かしてみることにする。
Tiger 言語から Dalvik アセンブリ言語へのコンパイラはほぼできていて、Dalvik アセンブリ言語から APK ファイルをつくるあたりもだいたいできているので、ちょっと手を加えてやれば、動かしてみることができるはず、なのだ。
えーと、なにが未だかというと、レジスタ割付けがまだなので(まだ Tiger Book は10章途中なの)、今回は、そこだけ人手で。
Tiger 言語のソースはこちら:
print("Hello, world!")
これを、現状のコンパイラでコンパイルした結果がこちら:
.class public Luhideyuki/daat/DaatProg;
.super Ljava/lang/Object;
.method public constructor <init>()V
.registers 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
---- prog ----
:L1
const-string t4, "Hello, world!"
move-object v0, t4
invoke-static {v0}, Luhideyuki/daat/DaatRuntime;->print(Ljava/lang/String;)Ljava/lang/Integer;
move-result-object t5
const t7, 0
new-instance t6, Ljava/lang/Integer;
invoke-direct {t6, t7}, Ljava/lang/Integer;-><init>(I)V
return-object t6
goto :L0
:L0
まだ、関数の prologue (宣言部分とか) が出力されていなかったり、レジスタ番号が仮のまま(t4, t5 とかは一時変数の番号そのまま)です。そこで、今回は人手で少し手を加えてあげます:
.class public Luhideyuki/daat/DaatProg;
.super Ljava/lang/Object;
.method public constructor <init>()V
.registers 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
.method public static main([Ljava/lang/Object;Ljava/lang/Integer;)Ljava/lang/Integer;
.locals 5
:L1
const-string v1, "Hello, world!"
move-object v0, v1
invoke-static {v0}, Luhideyuki/daat/DaatRuntime;->print(Ljava/lang/String;)Ljava/lang/Integer;
move-result-object v2
const v4, 0
new-instance v3, Ljava/lang/Integer;
invoke-direct {v3, v4}, Ljava/lang/Integer;-><init>(I)V
return-object v3
#goto :L0
#:L0
.end method
これを、別途用意したランタイム関数といっしょに assembly, apk builder etc. にかけて…
できました!:
Hello, world! だけではナンなので、もうちょっとだけプログラムっぽいのもやってみる。
これ:
for i := 1 to 5 do print("Hello! ")
これを、現状のコンパイラにかけたのがこれで、
.class public Luhideyuki/daat/DaatProg;
.super Ljava/lang/Object;
.method public constructor <init>()V
.registers 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
---- prog ----
:L4
const t7, 1
new-instance t6, Ljava/lang/Integer;
invoke-direct {t6, t7}, Ljava/lang/Integer;-><init>(I)V
move-object t4, t6
const t9, 5
new-instance t8, Ljava/lang/Integer;
invoke-direct {t8, t9}, Ljava/lang/Integer;-><init>(I)V
move-object t5, t8
:L1
check-cast t4, L/java/lang/Integer;
invoke-virtual {t4}, Ljava/lang/Integer;->intValue()I
move-result t10
check-cast t5, L/java/lang/Integer;
invoke-virtual {t5}, Ljava/lang/Integer;->intValue()I
move-result t11
if-le t10, t11, :L2
const t13, 0
new-instance t12, Ljava/lang/Integer;
invoke-direct {t12, t13}, Ljava/lang/Integer;-><init>(I)V
return-object t12
goto :L3
:L2
const-string t14, "Hello! "
move-object v0, t14
invoke-static {v0}, Luhideyuki/daat/DaatRuntime;->print(Ljava/lang/String;)Ljava/lang/Integer;
move-result-object t15
const t17, 1
new-instance t16, Ljava/lang/Integer;
invoke-direct {t16, t17}, Ljava/lang/Integer;-><init>(I)V
check-cast t4, Ljava/lang/Integer;
check-cast t16, Ljava/lang/Integer;
invoke-virtual {t4}, Ljava/lang/Integer;->intValue()I
move-result t19
invoke-virtual {t16}, Ljava/lang/Integer;->intValue()I
move-result t20
add-int t19, t19, t20
new-instance t18, Ljava/lang/Integer;
invoke-direct {t18, t19, Ljava/lang/Integer;-><init>(I)V
move-object t4, t18
goto :L1
:L3
手作業でレジスタ割付けなど少し手をくわえたのがこれ:
.class public Luhideyuki/daat/DaatProg;
.super Ljava/lang/Object;
.method public constructor <init>()V
.registers 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
.method public static main([Ljava/lang/Object;Ljava/lang/Integer;)Ljava/lang/Integer;
.locals 21
:L4
const v7, 1
new-instance v6, Ljava/lang/Integer;
invoke-direct {v6, v7}, Ljava/lang/Integer;-><init>(I)V
move-object v4, v6
const v9, 5
new-instance v8, Ljava/lang/Integer;
invoke-direct {v8, v9}, Ljava/lang/Integer;-><init>(I)V
move-object v5, v8
:L1
check-cast v4, Ljava/lang/Integer;
invoke-virtual {v4}, Ljava/lang/Integer;->intValue()I
move-result v10
check-cast v5, Ljava/lang/Integer;
invoke-virtual {v5}, Ljava/lang/Integer;->intValue()I
move-result v11
if-le v10, v11, :L2
const v13, 0
new-instance v12, Ljava/lang/Integer;
invoke-direct {v12, v13}, Ljava/lang/Integer;-><init>(I)V
return-object v12
#goto :L3
:L2
const-string v14, "Hello! "
move-object v0, v14
invoke-static {v0}, Luhideyuki/daat/DaatRuntime;->print(Ljava/lang/String;)Ljava/lang/Integer;
move-result-object v15
const v7, 1
new-instance v6, Ljava/lang/Integer;
invoke-direct {v6, v7}, Ljava/lang/Integer;-><init>(I)V
check-cast v4, Ljava/lang/Integer;
check-cast v6, Ljava/lang/Integer;
invoke-virtual {v4}, Ljava/lang/Integer;->intValue()I
move-result v9
invoke-virtual {v6}, Ljava/lang/Integer;->intValue()I
move-result v2
add-int v9, v9, v2
new-instance v8, Ljava/lang/Integer;
invoke-direct {v8, v9}, Ljava/lang/Integer;-><init>(I)V
move-object v4, v8
goto :L1
#:L3
.end method
そして、実行結果がこちら:
もうすこし複雑なプログラムを試すのは、レジスタ割付けを実装してからにしよう。
い、いちおう、今年中に動かした…かな?