Рассмотрим первую команду перехода — GOTO. Эта команда изменяет значение регистра PC таким образом, чтобы следующая IJVM-команда находилась в ячейке памяти с адресом, который вычисляется путем прибавления 16-разрядного смещения (со знаком) к адресу кода операции GOTO. Сложность здесь в том, что смещение связано со значением, находящимся в регистре PC в начале декодирования команды, а не тем, которое содержится в том же регистре после вызова 2 байт смещения.
Чтобы лучше это понять, посмотрите на рис. 4.17, а. Здесь показана ситуация, которая имеет место в начале цикла Mai ni. Код операции уже находится в регистре MBR, но значение PC еще не увеличилось. На рис. 4.17, б мы видим ситуацию в начале цикла gotol. В данном случае значение PC уже увеличено на 1, а первый байт смещения уже передан в MBR. В следующей микрокоманде (рис. 4.17, в) прежнее значение PC, которое указывает на код операции, сохраняется в регистре ОРС. Это значение требуется сохранять, поскольку именно от него, а не от текущего значения PC зависит смещение команды GOTO. И именно для этого предназначен регистр ОРС.
Микрокоманда goto2 начинает вызов второго байта смещения, что приводит к ситуации, показанной на рис. 4.17, г (микрокоманда goto3). После того как первый байт смещения сдвигается влево на 8 бит и копируется в регистр Н, мы переходим к микрокоманде goto4 (рис. 4.17, Э). Теперь у нас первый байт смещения, сдвинутый влево, находится в регистре Н, второй байт смещения — в реги стре MBR, а основание смещения — в регистре ОРС. В микрокоманде goto5 путем прибавления полного 16-разрядного смещения к основанию смещения мы получаем новый адрес, который помещается в регистр PC. Отметим, что в goto4 вместо MBR мы используем регистр MBRU, поскольку нам не требуется знаковое расширение второго байта. 16-разрядное смещение строится путем логического сложения (операция ИЛИ) двух половинок. Наконец, поскольку программа перед переходом к Mai ni требует, чтобы в MBR был помещен код следующей операции, мы должны вызвать этот код. Последний цикл, goto6, нужен для того, чтобы вовремя поместить данные из памяти в регистр MBR.
Рис. 4.17. Ситуация в начале выполнения различных микрокоманд: Mainl (a); gotol (б);
goto2 (е); goto3 (г); goto4 (д)
Смещения, которые используются в команде goto, представляют собой 16-разрядные значения со знаком в промежутке от -32 768 до +32 767. Это значит, что переходы на более дальние расстояния невозможны. Это свойство можно рассматривать либо как дефект, либо как особенность машины IJVM (а также JVM). Те, кто считает это дефектом, скажут, что машина JVM не должна ограничивать программиста. Те, кто считает это особенностью, скажут, что работа многих программистов продвинулась бы кардинальным образом, если бы им в ночных кошмарах приснилось следующее сообщение компилятора:
Программа слишком длинная и сложная. Вы должны переписать ее. Компиляция прекращена.
К сожалению (это наша точка зрения), это сообщение появится только в том случае, если объем предложения el se или then превысит 32 Кбайт, что составляет по крайней мере 50 страниц текста на языке Java.