POJ (JVM 上の Pascal) をフォローしていない人のために説明すると、これは サブセット を Pascal から JASM に変換するコンパイラーです ( Java アセンブリ) を使用して、JVM を実行環境として使用できるようにします。
前回の投稿では、Pascal の 関数 のサポートを実装しました。
この投稿では、クールなことについて話しますか?それほどではありません(笑)。今回はバグについてだけ話します :-)
JVM 用にコンパイルしているので、この素晴らしい仮想マシンのさまざまな点の機能を詳しく説明する必要があります。したがって、私はさまざまな機会に、JVM の内部機能とその命令 (オペコード) の一部について詳しく説明します。
変数宣言を実装したとき、JVM では main 関数の最初の変数が args (プログラムに渡される引数を含む配列) であるという事実に注意を払いませんでした。したがって、この PR では、引数の最初の位置を暗黙的に予約しています。
テスト用の Pascal プログラムにはグローバル変数のみが含まれていたため、JASM 生成における重大なエラーには気づきませんでした。グローバル変数とローカル変数を含むプログラムを作成した瞬間、何かがおかしいことに気づきました (笑)。
以下の Pascal プログラムより:
program global_var_declaration; var globalvar : integer; begin globalvar := 123; write (globalvar); end.
POJ は次の JASM を生成しました:
// Code generated by POJ 0.1 public class global_var_declaration { public static main([java/lang/String)V { ;; globalvar := 123; bipush 123 istore 1 ;; write (globalvar); getstatic java/lang/System.out java/io/PrintStream iload 1 invokevirtual java/io/PrintStream.print(I)V return } }
問題を特定するために、上記の Pascal プログラムと同等の Java プログラムを作成しました。
public class GlobalVarDeclaration { public static int globalVar; public static void main(String[] args) { globalVar = 123; System.out.println(globalVar); } }
クラスを逆アセンブルすると、次のアセンブリが得られました:
1: public class GlobalVarDeclaration { 2: public static globalVar I 3: 4: public static main([java/lang/String)V { 5: bipush 123 6: putstatic GlobalVarDeclaration.globalVar I 7: 8: getstatic java/lang/System.out java/io/PrintStream 9: getstatic GlobalVarDeclaration.globalVar I 10: invokevirtual java/io/PrintStream.println(I)V 11: 12: return 13: } 14: }
この時点で、宣言 "public static globalVar I" (2 行目) と命令 putstatic (6 行目) および getstatic (行目) に気づきました。 9) 。予期されていたのは、これまで POJ で使用されていた astore 命令と istore 命令でした。 JVM ドキュメントを読んでいると、POJ が JVM に対する関数のローカル変数であるかのようにグローバル変数を宣言していることに気付きました:-D
とにかく、今まで POJ は (誤って) opcodes aload/iload/astore/ istore はグローバル変数の場合ですが、正しいオプションは変数を public として宣言し (2 行目のように)、getstatic/putstatic.
を使用することです。これにより、シンボル テーブルがローカル宣言とグローバル宣言を処理できるように、コードがリファクタリングされました。そしてここでは、シンボル テーブルがローカル変数とグローバル変数に対して正しい命令を生成できるようにコードがリファクタリングされました。
JASM コード生成は、新しいシンボル テーブルを処理し、関数またはプロシージャの終了後にローカル宣言をクリーンアップするためにここで変更されました。
これにより、以下の Pascal プログラムから:
program GlobalVarDeclaration; var globalvar : integer; begin globalvar := 123; write (globalvar); end.
POJ は次の JASM を正しく生成するようになりました:
// Code generated by POJ 0.1 public class global_var_declaration { public static globalvar I public static main([java/lang/String)V { ;; globalvar := 123; bipush 123 putstatic global_var_declaration.globalvar I ;; write (globalvar); getstatic java/lang/System.out java/io/PrintStream getstatic global_var_declaration.globalvar I invokevirtual java/io/PrintStream.print(I)V return } }
次の投稿では、コンテキストとネストされた文について説明します。
プロジェクトの完全なコードとドキュメントが含まれるリポジトリはここにあります。
以上がいくつかのバグの解決の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。