ホームページ >バックエンド開発 >Golang >いくつかのバグの解決

いくつかのバグの解決

王林
王林オリジナル
2024-07-24 14:23:311032ブラウズ

Resolução de alguns bugs

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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:生産者/消費者次の記事:生産者/消費者