· i - int (также byte, short, char и boolean),
· l - long,
· f - float,
· d - double,
· a - ссылка на объект или массив.
Кроме того, есть несколько команд, работающих с типами char, byte и short.
Можно выделить несколько групп команд по назначению:
· команды загрузки и сохранения:
o Загрузка локальной переменной на стек: iload, iload_<n>, lload, lload_<n>, fload, fload_<n>, dload, dload_<n>, aload, aload_<n>;
o Сохранение значения с вершины стека в локальной переменной: istore, istore_<n>, lstore, lstore_<n>, fstore, fstore_<n>, dstore, dstore_<n>, astore, astore_<n>;
o Загрузкаконстантнастек: istore, istore_<n>, lstore, lstore_<n>, fstore, fstore_<n>, dstore, dstore_<n>, astore, astore_<n>;
· арифметические и логические команды:
o сложение: iadd, ladd, fadd, dadd;
o вычитание: isub, lsub, fsub, dsub;
o умножение: imul, lmul, fmul, dmul;
o деление: idiv, ldiv, fdiv, ddiv;
o остаток: irem, lrem, frem, drem;
o изменение знака: ineg, lneg, fneg, dneg;
o сдвиги и побитовые операции: ior, lor, iand, land, ixor, lxor, ishl, ishr, iushr, lshl, lshr, lush;
o сравнение: dcmpg, dcmpl, fcmpg, fcmpl, lcmg;
o инкремент локальной переменной: iinc.
Все эти команды, за исключением iinc, не имеют параметров. Они извлекают операнды с вершины стека и записывают результат на вершину стека. Команда iincимеет два операнда - индекс локальной переменной и величину, на которую значение данной переменной должно быть изменено;
· команды преобразования типов:
o расширяющее: i2l, i2f, i2d, l2f, l2d, f2d;
o сужающее: i2b, i2c, i2s, l2i, f2i, f2l, d2i, d2l, d2f;
· команды работы с объектами и массивами:
o создание объекта: new;
o создание массива: newarray(примитивного типа), anewarray (ссылочного типа), multianewarray(многомерного);
o доступ к полям: getfield, putfield(для полей экземпляра), getstatic, putstatic (для статических полей);
o загрузка элемента массива на стек: baload(тип byte), caload (тип char), saload(тип short), iaload, laload, faload, daload, aaload;
o сохранение значения с вершины стека в элемент массива: bastore, castore, sastore, iastore, lastore, fastore, dastore, aastore;
o получение размера массива: arraylength;
o проверка типов: instanceof(возвращает на вершине стека логическое значение) и checkcast (генерирует исключение в случае несоответствия типа ссылки на вершине стека требуемому типу);
· команды манипуляций со стеком операндов:
o pop - удаление верхнего элемент стека;
o pop2 - удаление двух верхних элемента стека;
o dup, dup2, dup_x1, dup2_x1, dup_x2, dup2_x2 - дублирование элементов на вершине стека;
o swap - перемена местами двух верхних элементов стека;
· команды безусловной передачи управления:
o jsr, jsr_w, ret - вызов подпрограмм и возврат из них. Используются при компиляции блока finally;
o goto, goto_w- безусловный переход;
· команды условного перехода:ifeq, iflt, ifle, ifne, ifgt, ifge, ifnull, ifnonnull, if_icmpeq, if_icmpne, if_icmplt, if_icmpgt, if_icmple, if_icmpge, if_acmpeq, if_acmpne;
· команды вызова методов:
o invokevirtual - обычный вызов метода экземпляра с использованием механизма позднего связывания;
o invokestatic - вызов статического метода;
o invokeinterface - вызов метода интерфейса у объекта, реализующего данный интерфейс;
o invokespecial - вызов метода экземпляра без использования механизма позднего связывания. Используется для вызова конструкторов, методов суперкласса и private-методов;
· команды возврата из метода:
o return - возврат из метода, возвращающего void;
o ireturn, lreturn, freturn, dreturn, areturn - возврат значения соответствующего типа;
· команда генерации исключений: athrow;
· команды синхронизации (механизм блокировок):
o monitorenter- установить блокировку (войти в критическую секцию);
o monitorexit - освободить блокировку (выйти из критической секции).
Файл исходного текста на языке ассемблера для платформы Java (языке JASM) представляет собой текстовый файл, строки которого разделены последовательностью символов с кодами 13 и 10. Имя файла исходного текста и его расширение могут быть любыми, однако рекомендуется, чтобы имя совпадало с именем описанного в файле класса, а расширением было .jasm либо .jsm. Файл исходного текста состоит из предложений, разделенных точкой с запятой. Последнее предложение может не иметь в конце точки с запятой. Комментарии отделяются знаком процента и распространяются до конца строки. Точки с запятой и знаки процента внутри строковых констант, ограниченных двойными кавычками, не имеют своего специального значения. Две идущие подряд двойные кавычки внутри строковой константы интерпретируются как одна двойная кавычка в строке. Любые последовательности пробельных символов (пробелов, табуляций, переводов строки и т. д.) интерпретируются как один пробел, если с обеих сторон от них находятся символы следующих видов: буквы латинского алфавита, цифры, знак подчеркивания, либо, в противном случае, игнорируются. Исключение составляют пробельные символы в строковых константах и комментариях. Верхний и нижний регистр букв в идентификаторах, именах команд и других лексемах различается.
Каждый файл исходного текста компилируется в один файл класса. Файл исходного текста должен иметь следующую структуру:
[модификаторы_доступа] {class|interface} <имя_класса>;
[extends <базовый класс>;]
[implements <интерфейс_1>, <интерфейс_2>, ... , <интерфейс_n>;]
[fields;
<описания_полей>
]
[methods;
<описания_методов>
]
Здесь и далее в квадратные скобки заключены необязательные элементы, в фигурные - альтернативные варианты (разделены вертикальной чертой), в угловые - нетерминальные символы.
Модификаторы_доступа - это слова public, final, abstract, super, соответствующие флагам прав доступа ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT, ACC_STATIC. Эти флаги устанавливаются в единицу тогда и только тогда, когда в объявлении класса присутствует соответствующее ключевое слово. Класс может иметь несколько различных модификаторов доступа, разделенных пробелом (или любой другой последовательностью пробельных символов). Повторение одинаковых модификаторов в заголовке одного класса не допускается. Когда класс не имеет флага ACC_INTERFACE, в его объявлении используется слово class, иначе используется ключевое слово interface. Все имена классов и интерфейсов записываются с указанием полного пути (пакетов, в которых эти классы содержатся). Имена пакетов и класса отделяются точкой, например, java.lang.String. В аргументах команд, там, где это необходимо, вместо полного имени текущего класса можно использовать символ «@». Если базовый класс не указан (предложение extendsотсутствует), то по умолчанию используется java.lang.Object. Интерфейсы - предки описываемого интерфейса записываются в секции implements.
Для идентификаторов - имен пакетов, классов, полей и методов, а также меток, используются следующие правила: они должны состоять из букв латинского алфавита любого регистра (регистр имеет значение), знаков подчеркивания и цифр, причем не должны начинаться с цифры. Настоятельно не рекомендуется использование идентификаторов, совпадающих с ключевыми словами языка Java, что может привести к некорректной компиляции, либо интерпретации файлов классов JVM. Два специальных имени <init> и <clinit> также рассматриваются как идентификаторы.
Простейший пример описания класса, не имеющего полей и методов:
public abstract class some_package.SomeClass;
% это комментарий
extends
some_package.nested_package1.BaseClass;
implements % и это комментарий
some_package.Interface1, some_package.nested_package2.Interface2;
Описание поля имеет следующий вид:
[модификаторы_доступа] <имя_поля>:<тип_поля> [=<начальное значение>];
Здесь модификаторы_доступа - следующие слова: public, protected, private, final, static, transient, volatile, соответствующие флагам доступа поля ACC_PUBLIC, ACC_PROTECTED, ACC_PRIVATE, ACC_FINAL, ACC_STATIC, ACC_TRANSIENT, ACC_VOLATILE. Повторение одинаковых модификаторов доступа в объявлении одного поля и сочетания модификаторов, соответствующие запрещенным сочетаниям флагов доступа (см. The Java Virtual Machine Specification), вызываютошибкувременикомпиляции. Поля интерфейса обязательно должны быть объявлены с модификаторами public, static и final. Имя_поля - корректный идентификатор. Тип_поля - имя класса либо имя примитивного типа (имена примитивных типов совпадают с соответствующими ключевыми словами языка Java - byte, short, int, long, char, float, double, boolean). Начальное значение может быть задано только для статического поля, если оно указано, то у поля создается атрибут ConstantValue. Начальное значение может быть целочисленной, вещественной, логической либо символьной константой для полей соответствующих типов. Вещественная константа может быть записана в десятичной либо экспоненциальной форме, в формате вещественных чисел, принятом в Java. Символьные константы заключаются в апострофы. Кроме того, может быть указан код символа как обычное целое число. Логические константы записываются в виде слов trueи false. Примеры описаний полей:
public final static COUNT:int = 10;
static c:char = ‘A’;
static c1:char = 13;
private volatile m_flag:boolean;
protected m_list:java.util.ArrayList;
Описание метода в общем случае имеет вид: