• ベストアンサー

Jasminを使用して10桁のフィボナッチ数列を表すには・・・??

初投稿です、よろしくお願いします。 プログラミング初心者で、まだ右も左もよく分からないヒヨッコですが、 この間学校でjasminコードというものを習い始め、まだちゃんと理解していないうちに、こんな問題を出されました。 ================================ 以下のコードをjasminで表しなさい。 public class exam2 { public static void main(String args[]) { dofib(9); } public static void dofib(int n) { int n1 = 0; int n2 = 1; int tmp; if ((n < 0) || (n == 0)) System.out.println("0"); for (int i = 0; i < n; i++) { System.out.println(n1 + " "); tmp = n2; n2 = n1 + n2; n1 = tmp; } } } フィボナッチ数列を10桁まで表示するコードです。 ================================ 私と友達が作ってみたjasminコードはこちらです。 .class public examples/Fibo .super java/lang/Object ; ; standard initializer .method public <init>()V aload_0 invokenonvirtual java/lang/Object/<init>()V return .end method .method public static main([Ljava/lang/String;)V .limit locals 5 .limit stack 10 getstatic java/lang/System/out Ljava/io/PrintStream; astore_1 bipush 10 istore_2 iconst_0 dup ;invokevirtual java/io/PrintStream/println(I)V; ;invokestatic java/lang/String/valueOf(C)Ljava/lang/String; invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V istore_3 bipush 1 istore 4 L0: iload 3 dup iload 4 dup ;invokestatic java/lang/String/valueOf(C)Ljava/lang/String; invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V iadd iload 4 istore 3 istore 4 iload_2 ifeq L1 iinc 2 -1 goto L0 L1: return .end method しかし、これではうまく動作しませんでした。 何か解決方法や提案など、ございましたら教えていただけたら幸いです。 どうぞよろしくお願いします。

  • Java
  • 回答数4
  • ありがとう数6

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

先生の意図も質問文のjasminのコードも(どの行がどの行に対応するのかも)さっぱりだ。 一行一行丁寧に訳す。 心残り: 1.ラベルを大量に使っちゃったこと 2.ループ変数のスコープがループではなくメソッドになってしまっている 3.前方が真だったとき,後者は実行しないかもしれないけど, 書いたコードでは両方実行しちゃっていること 4.スタックサイズと変数の数の見積もりがいい加減なこと #初めて触った言語。new instructionには戻り値がなく,さらにコンストラクタを別に呼び出さないといけないということが分からず一時間くらい迷走したが,一応コード完成。 #なお,このコードは逆アセンブルしたものとは異なるだろう #WikipediaのJava仮想マシンのオペコードの説明が参考になった。 メモ: bipush等はbyte型で,高速らしいが,混乱するのでint型に集中できるようldcを使った。 iload_0等はよく使うから用意してあるらしいが iload_3までしかなく,iload_4とかやろうとしてエラーに見舞われたので iload 0 とちゃんと分けて書くことにした。 混乱したので, 自分は割り切って istore (スタックから取り出して,その番号の領域に入れる) iload (指定した番号スタックに積む) しか使わないことに決めた。 #↓念のためスタックの図。先は読まなくていい #http://www.cc.kyoto-su.ac.jp/~yamada/ap/stack.html #型によってiload fload,dload,aloadを使い分ける(順にint,float,double,それ以外) インスタンスメソッドを使うには インスタンスをスタックに積んでおいて invokevirtual メソッド名(引数の型)戻り値 スタティックなメソッドを実行する時は invokestatic メソッド名(引数の型)戻り値 java.lang.System.outはSystemクラスのstaticなメソッドでjava.io.PrintStreamのインスタンスを返す。 printlnはjava.io.PrintStreamクラスのインスタンスメソッド その後引数に必要なものを積む。 メソッドを使う直前に使うものを全てのものを引き出すことを意識する。 メソッドやisub,iaddを使った後は… インスタンス,引数に渡した物はそれぞれ消えて,戻り値がスタックに積まれる。 その引数をすぐに使わない場合はstoreしておく。 どうしても混乱する場合は後で使うことを前提に変数に入れてしまおう。 System.outのようにどこかのstaticなメソッドを実行するのではなく インスタンスを生成する場合は new クラス dup invokespecial コンストラクタ を行うことでスタックに積まれるようだ。 変数に入れる必要がないのにスタックに余ってしまった物はpopする。 .class public exam6 .super java/lang/Object ; standard initializer .method public <init>()V aload 0 invokenonvirtual java/lang/Object/<init>()V return .end method ; public static void dofib(int) .method public static dofib(I)V ; set limits used by this method .limit locals 15 .limit stack 15 ;int0:n ;int1:n1 ;int2:n2 ;int3:tmp ;int4:i(loop variable,but I don't know how to declare only for the loop) ;n1 = 0 ldc 0 istore 1 ;n2 = 1 ldc 1 istore 2 ; leftexpression or right expression ;left expression ;n < 3 → n - 3 < 0 ;n < 0 → n - 0 < 0 ;n - 0 iload 0 ldc 0 isub ;load 1(true) or 0(false) onto stack,so that I can use it with ior later. ;after that, goto MIXAFTER1 ifle MIXLOGOP1 goto MIXLOGOP2 MIXLOGOP1: ldc 1 goto MIXAFTER1 MIXLOGOP2: ldc 0 goto MIXAFTER1 MIXAFTER1: ;right expression ;n - 0 < 0 iload 0 ldc 0 isub ;load 1(true) or 0(false) onto stack,so that I can use it with ior later. ;after that, goto MIXAFTER2 ifeq MIXLOGOP3 goto MIXLOGOP4 MIXLOGOP3: ldc 1 goto MIXAFTER2 MIXLOGOP4: ldc 0 goto MIXAFTER2 MIXAFTER2: ior ifne IFLABEL1 goto IFLABEL2 IFLABEL1: ;I think it's better to write in the original Java Source Code ;getstatic java/lang/System/out Ljava/io/PrintStream; ;ldc 0 ;invokevirtual java/io/PrintStream/println(I)V getstatic java/lang/System/out Ljava/io/PrintStream; ldc "0" invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V ;may be the original Java source lacks "return" here. IFLABEL2: ;i = 0 ldc 0 istore 4 ;start loop WHLABEL1: ;check for the loop constraints ;i < n ;i - n < 0 iload 4 iload 0 isub iflt WHINNER1 goto WHAFTER1 WHINNER1: ;I think it's better to write in the original Java Source Code ;getstatic java/lang/System/out Ljava/io/PrintStream; ;iload 1 ;invokevirtual java/io/PrintStream/println(I)V getstatic java/lang/System/out Ljava/io/PrintStream; new java/lang/StringBuffer dup invokespecial java/lang/StringBuffer/<init>()V iload 1 invokestatic java/lang/Integer/toString(I)Ljava/lang/String; invokevirtual java/lang/StringBuffer/append(Ljava/lang/String;)Ljava/lang/StringBuffer; ldc " " invokevirtual java/lang/StringBuffer/append(Ljava/lang/String;)Ljava/lang/StringBuffer; invokevirtual java/lang/StringBuffer/toString()Ljava/lang/String; invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V ;tmp = n2 iload 2 istore 3 ;n2 = n1 + n2; iload 1 iload 2 iadd istore 2 ;n1 = tmp; iload 3 istore 1 ;i++ iload 4 ldc 1 iadd istore 4 goto WHLABEL1 WHAFTER1: return .end method .method public static main([Ljava/lang/String;)V .limit stack 5 .limit locals 100 ldc 9 invokestatic exam6/dofib(I)V return .end method

beginnerCS
質問者

お礼

>>himajin100000さん ご返信、どうもありがとうございます。 一行一行丁寧に訳す。了解しました。やはり全てのコードについて、 なぜこうなるのか?が分からなければダメですね。元あるコードを繋いで、なんとなくプログラムを組むのではなく、しっかり意味を追って1行1行を理解しなければ何の意味もありませんよね。 それと、貴重な回答例どうもありがとうございます!時間も大分かけさせてしまったみたいで、ご迷惑をおかけしました・・・。 メモやスタックの図など、参考にしながらコードを読み解きたいと思います。自分の滅茶苦茶なコードもどうにかしなければなりませんし。

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

心残り2 については, JVM では不可能だったはずです>#3. あと細かいところでは ・new は「新しく作ったオブジェクト」をスタックに残します. だから, dup+コンストラクタ呼び出しで初期化できます. ・for や while は「条件判断をループ本体のあとに書く」ようにコンパイルすることになっているので, そのコードは逆アセンブルしたものと確実に異なるはずです.

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

う~ん, 方針がよくわからんなぁ. 「Java を習っていない」=「Java を知らない」ことを前提にしてしまうと, 「以下のコードをjasminで表しなさい」という問題そのものが成り立たないんだが.... なお, 「うまく動作しない」というときには「どのような動作を期待したか」「実際にはどのような動作であったか」を書くようにしてください. また, 何かメッセージが出力される場合にはそれもつけてください. しかし謎のプログラムだなぁ. 例えば getstatic java/lang/System/out Ljava/io/PrintStream; astore_1 ってやってるけど, その後この変数は 1回も使ってないよね.

beginnerCS
質問者

お礼

続いてのご返信、どうもありがとうございます。 先生の方針は私も理解しかねています。しかしC#を他クラスで学んでいるので、『このぐらいのコードは分かるだろう。』と先生は考えているのでは、と自分を納得させています。 申し訳ありません、説明不足でしたね。期待する動作は 0 1 1 2 3 5 8 13 21 34 とjasminのファイルを実行した時に表示されることです。 今のところ現れるエラーメッセージは C:\Users\YDI\Desktop\jasmin\jasmin>java -cp . examples/Fibo Exception in thread "main" java.lang.VerifyError: (class: examples/Fibo, method: main signature: ([Ljava/lang/String;)V) Expecting to find object/array on stack Could not find the main class: examples/Fibo. Program will exit. 謎のプログラム、その通りだと思います。jasminをついこの間知ったばかりで、先生に教えてもらった数例(forループをjasminで表す等)を参考にしながら手探り状態で書いたものなので極めて稚拙なコードになっているのでしょう。本当に初心者で申し訳ありません。いくつかサイトを見てみたのですが、jasminコードがしっかり日本語で説明されているサイトがなかなか見つからず、今回質問させていただいた次第です。 getstatic java/lang/System/out Ljava/io/PrintStream; astore_1 は astore_1に java/lang/System/out Ljava/io/PrintStream というコードが入れられていると思っていました・・・。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「一度 Java で書いてから逆アセンブルする」のはダメなんだろうか.

beginnerCS
質問者

お礼

Tacosanさん さっそくのご回答、どうもありがとうございます。 逆アセンブルなんて方法があったとは!!知りませんでした。 ただ、『javaを学ぶ前にjasminを学ぶ』という先生の方針なので、 まだjavaを習っていないのです。 C#ならば他の授業で習っているので分かるのですが・・・。 ただ、後々に使えそうな知識ですね! ご提案、どうもありがとうございました。

関連するQ&A

  • プログラムの合体。

    jump7799_4836さん 2018/7/2103:34:44 public class Test2 { public static int メソッド () { System.out.println("メソッド()が呼ばれました"); return 0; } public static int メソッド (int i) { System.out.println("メソッド(int i)が呼ばれました"); return i; } public static int メソッド (int i, int j) { System.out.println("メソッド(int i, int j)が呼ばれました"); return i; } public static int メソッド (short s) { System.out.println("メソッド(short s)が呼ばれました"); return s; } public static int メソッド (double d) { System.out.println("メソッド(double d)が呼ばれました"); return (int) d; } } public メソッド class Test2 { public メソッド static void main(String[] args) { Test2.メソッド (); Test2.メソッド (1); Test2.メソッド (1,2); Test2.メソッド (1.1); Test2.メソッド ((short) 1); Test2.メソッド ((double)1); } } kouzou@GD348ZZD9:/WORK$ javac Test2.java Test2.java:29: エラー: class、interfaceまたはenumがありません public メソッド class Test2 { ^ Test2.java:30: エラー: <identifier>がありません public メソッド static void main(String[] args) { ^ エラー2個 2つのプログラムが合体することってあるのですか? いつもすみません。 解説のほど、宜しくお願い申し上げます。

    • ベストアンサー
    • Java
  • フィボナッチ数列の配列について

    public class Fibonacci { public static void main(String[] args) { int [] fibAray = new int [20]; //フィボナッチ数列用の配列 fibAray[4] = 3; fibAray[1] = 1; for (int i = 0; i < fibAray.length; i++) { fibAray[i] = i + 1; } for (int i = 0; i < fibAray.length; i++) { System.out.println( "第" + (i + 1) + "頁は" + 3); } } } フィボナッチ数列の第20項までを配列にし、それらを"第4項は3"のように表示する。 という問題で作ったプログラムですが1項~20項まで3と表示されます。 これで合ってるのでしょうか?

    • ベストアンサー
    • Java
  • System.out.printlnの仕組み

    javaのSystem.out.println();について質問です。 System.out.println()の仕組みのサンプルコードを、以前書籍かサイトで見かけました。 それを見る限り この out は、Systemクラスのフィールド、定数out(静的)でPrintStream型のようでした。 そして、このPrintStream型の定数にPrintStreamのインスタンスを代入していました。 定数outはstaticだったのでSystem.out とSystemクラスはnewせずに直接呼べて、 定数自体にはPrintStreamインスタンスの参照が格納されているので printlnメソッドは、PrintStreamクラスのものかなと思いました。 疑問なのは、Systemクラスの定数に わざわざPrintStreamインスタンスを代入して PrintStreamクラスのメソッドを呼んでいるのかということです。 なぜPrintStreamクラスのprintlnメソッドを使うために PrintStreamクラスとSystemクラスの両方を使用するかが見えてきません。 詳しい方おられましたら教えてもらえないでしょうか?

  • この行に複数のマーカーがあります。

    JAVA初心者です。教科書通りに入力したにもかかわらずエラーが出てしまいます。 5行目に「この行に複数のマーカーがあります。iを変数に解決できません。」と出ます。どう解決したらいいのでしょうか。用語などもまだ抑えきれていないので丁寧な解説お願いします。 1 public static void main(String[] args) { 2 // TODO 自動生成されたメソッド・スタブ 3 int n =0; 4 for (int i = 1; i < 10000;i++); 5 n += i ; 6 System.out.println(n); 7 } }

  • Integerについて

    class Sample5_7_Integer { /** * Integerクラスのメソッド */ public static void main(String[] args) { //String → int int i1 = Integer.parseInt(args[0]); //int型にすることにより計算可能 System.out.println(i1 + 100); //String → integer Integer i2 = Integer.valueOf(args[0]); System.out.println(i2); Integer i3 = new Integer(100); System.out.println(i2.equals(i3)); } } をEclipseで実行したところ、 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0 at benkyou.Sample5_7_Integer.main(Sample5_7_Integer.java:10) というエラーになってしまいます。 どなたか解決法をお願いします。

    • ベストアンサー
    • Java
  • javaのコンパイルエラーについて質問

    macにてjavaを学習し始めた初心者です 真っ先に習うHello Worldのソースコードを書き、 class Hello01 { public static void main(String args[]){ System.out.printin("Hello Java World!"); } } コンパイルをしたところ以下のようなコンパイルエラーが表示されました Hello01.java:3: cannot find symbol symbol : method printin(java.lang.String) location: class java.io.PrintStream System.out.printin("Hello Java World!"); ^ どこかソースに欠けてる箇所があるのだと思いますが、 どこが間違っているのかいまいち分かりません。 どなたか分かる方、教えていただけますか? よろしくお願いします

    • 締切済み
    • Mac
  • System.out.printlnの意味がよくわかりません。

    System.out.printlnの意味がよくわかりません。 色々と参考書などを読むと、「Systemのフィールド変数outは、PrintStreamクラスのインスタンスを参照している。」との記述がありました。 ならばと、直接io パッケージからPrintStream 、outを呼び出すため、 “java.io.PrintStream.out. println();”と書きましたが、「outが不可視です」とのエラーが出ます。 このコマンドのどこが間違っているのでしょうか。 また、何故、Systemから、他のパッケージにあるメソッドを呼び出すのでしょうか。 わざわざSystemから、ioパッケージにあるout 、println() を呼び出す必要があるのでしょうか。 他の呼び出し方はないのでしょうか。;

    • ベストアンサー
    • Java
  • 配列クラスのクラス名

    配列クラスのクラス名 配列クラスのクラス名を教えてください。 配列はクラスですよね。そこまでは分かります。 こんなコードを実行しましたが System.out.println((new int[0]).getClass()); System.out.println((new boolean[0]).getClass()); System.out.println((new String[0]).getClass()); System.out.println((new Integer[0]).getClass()); 親切にこのような結果を出力してくれます。 class [I class [Z class [Ljava.lang.String; class [Ljava.lang.Integer; 結果として配列が何というクラスなのかは分かりません。 (もしかして『[I』『[Z』『[L』という名前のクラスでしょうか?) 昔Javaのソースを読んだときに、配列クラスのファイルも 読んだことがあるような気がするのですが、 なんと言うクラスだったか忘れてしまいました。 パッケージ名+クラス名を教えてください。 よろしくお願いします。

    • ベストアンサー
    • Java
  • 戻り値を使用する呼出

    java勉強中の初心者です。 引数で値を受け取り、英語表記の曜日メソッドを定義して main()メソッドから呼び出します。この時に、戻り値を 表示する際に日本語に変換して表示を行う時にはどうしたらよいか 教えていただけますか? ------------------------------------------------- 入力ストリームでの入力値:20061110 実行結果:2006/11/10は木曜日です ------------------------------------------------- import java.io.*; import java.util.*; public class Sample { public static void main(String args[])throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String s = br.readLine(); int n = Integer.parseInt(s); dispDayOfWeek(n); } static void dispDayOfWeek(int a){ Calendar time = new GregorianCalendar(); int y = time.get(time.YEAR); int m = time.get(time.MONTH) + 1; int d = time.get(time.DATE); //System.out.println( y + "/" + m + "/" + d + "は" + "です"); } } ------------------------------------------------------------ このような感じでなんとなくはつかめてはいると 思うのですが、よろしくお願いします。

    • ベストアンサー
    • Java
  • APIの非奨励クラス?

    失礼致します。 質問させてください。 今、java.util.regex.PatternをインポートしてPattern下のquoteメソッドを使ったところ「java.lang.NoSuchMethodError: java.util.regex.Pattern.quote(Ljava/lang/String;)Ljava/lang/String;」 というエラーが出ました。 ローカルではこのメソッドを使い、問題なく動いているにもかかわらずです。PatternクラスはAPIに掲載されているのですがquoteはありませんでした。このメソッドは削除されたのでしょうか?誰かご存知の方、教えて頂けますでしょうか?

    • ベストアンサー
    • Java

専門家に質問してみよう