«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Исправление некоторых ошибок

Исправление некоторых ошибок

Опубликовано 19 августа 2024 г.
Просматривать:974

Resolução de alguns bugs

Для тех, кто не следит за POJ (Pascal на JVM) — это компилятор, преобразующий подмножество из Pascal в JASM (Java Assembly), чтобы мы могли использовать JVM в качестве среды выполнения.

В последнем посте мы реализовали поддержку функций Pascal.

В этом посте мы поговорим о крутых вещах? Не так уж и лол. На этот раз мы поговорим только об ошибках :-)

Поскольку мы компилируем для JVM, необходимо подробно описать работу различных точек этой невероятной виртуальной машины. Поэтому в разное время я подробно описываю внутреннее функционирование JVM, а также некоторые ее инструкции (коды операций).

Ошибка с параметрами, передаваемыми в программу через командную строку.

Когда я реализовал объявление переменной, я не обратил внимания на то, что в JVM первой переменной в основной функции является args, массив, содержащий аргументы, передаваемые в программу. Поэтому в этом PR я неявно резервирую первую позицию для args.

Ошибка при работе с локальными и глобальными переменными.

Поскольку тестовые программы на Паскале содержали только глобальные переменные, я не заметил серьезной ошибки при генерации JASM. В тот момент, когда я создал программы, содержащие глобальные и локальные переменные, я понял, что что-то не так, лол.

Из программы на Паскале ниже:

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
    }
}

Чтобы попытаться определить проблему, я создал программу на 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) . Ожидалось, что инструкции astore и istore используются POJ до сих пор. Читая документацию JVM, я понял, что POJ объявляет глобальные переменные, как если бы они были локальными переменными функции для JVM: -D

Во всяком случае, до сих пор POJ (ошибочно) использовал опкоды aload/iload/astore/ Istore для глобальных переменных, но правильным вариантом было бы объявить переменные как общедоступные (как в строке 2) и использовать getstatic/putstatic.

В результате код был реорганизован, чтобы таблица символов могла обрабатывать локальные и глобальные объявления. И здесь код был реорганизован, чтобы таблица символов могла генерировать правильные инструкции для локальных и глобальных переменных.

Здесь изменена генерация кода JASM для обработки новой таблицы символов, а также очистки локальных объявлений после завершения функции или процедуры.

При этом из программы на Паскале ниже:

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
    }
}

Следующие шаги

В следующем посте мы поговорим о контекстах и ​​вложенных предложениях.

Полный код проекта

Репозиторий с полным кодом и документацией проекта находится здесь.

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/alexgarzao/resolucao-de-alguns-bugs-3a1i?1. В случае нарушения авторских прав свяжитесь с [email protected], чтобы удалить ее.
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3