Форматы команд машинного языка
Команда центрального процессора состоит из кода операции и одного или
нескольких операндов (объектов, над которыми
совершается операция). В зависимости от числа операндов, команды делятся
на безадресные (не имеющие операндов или имеющие
неявно указанные), одноадресные (производящие
операцию над одним объектом или одним явно и одним или несколькими неявно
указанными), двух- и трехадресные.
Встречаются архитектуры, в которых есть команды и с большим числом операндов,
но это экзотика.
Примеры безадресных команд без операнда.
- NOP
- No OPeration, отсутствие операции.
- HALT
- Остановка процессора
Примеры безадресных команд с неявно указанными операндами
- RETURN
- Возврат из подпрограммы. Выталкивает из стека адрес возврата и помещает
его в счетчик команд.
- WDR
- WatchDog Reset, сброс сторожевого таймера микроконтроллера.
- ADD
- Вытолкнуть из стека два значения, сложить их и протолкнуть результат
в стек.
- scs
- Skip if Carry Set, пропустить следующую команду, если бит переноса
в слове состояния установлен.
Примеры одноадресных команд с одним операндом
- INC x
- INCrement, добавить к операнду 1 и сохранить результат по тому же
адресу.
- TST х TeST,
- установить в слове состояния флаги знака и равенства нулю в соответствии
со значением операнда.
Примеры одноадресных команд с неявным операндом.
- ADD x [, Асс]
- Сложить операнд с аккумулятором и сохранить результат в аккумуляторе.
- PUSH х
- Протолкнуть значение операнда в стек.
- CALL x
- Вызов подпрограммы, сохраняет адрес следующей команды в стеке и передает
управление по указанному адресу.
- BNEQ х
- Передает управление по указанному адресу, если в слове состояния
установлен флаг равенства нулю.
Примеры двух- и трехадресных команд.
Присвоить значение объекта х объекту у.
Сложить х и у, поместить результат в у.
Сложить х и у и поместить результат в z.
Четырехадресная команда:
DIV х, у, z, w
выполняет деление х на у,
помещает частное в z, а остаток — в w.
Шестиадресная команда:
INDEX b, I, h, s, i, a
вычисляет адрес элемента массива, расположенного по адресу b,
с нижней и верхней границами индекса I и b
соответственно и размером элемента s.
Операнд i — индекс элемента, а
— место, куда следует поместить вычисленный адрес.
Количество адресов иногда используют и для общей характеристики системы
команд. Двухадресной называют систему команд, в которой команды имеют
максимум два операнда, трехадресной -- максимум три. Нередко, впрочем,
вместо максимального количества операндов, адресность системы команд определяют
по количеству операндов у наиболее "ходовых" команд — сложения
и вычитания. Таким образом, VAX, из системы команд которого взяты примеры
четырех- и шестиадресных команд, часто относят к трехадресным архитектурам.
Одноадресные системы команд обычно используют в качестве неявно заданного
операнда выделенный регистр, так называемый аккумулятор,
или стек. Такие архитектуры называют, соответственно, аккумуляторными
и стековыми.
Одноадресную аккумуляторную архитектуру имеют микроконтроллеры семейства
PIC фирмы Microchip. Большинство современных процессоров имеют двух- и
трехадресные системы команд.
На примере стековой команды ADD мы видели, что
многие из команд стековой архитектуры могут обойтись вообще без явно указанных
операндов, однако команды проталкивания значений переменных в стек и выталкивания
их оттуда все-таки необходимы, поэтому все стековые архитектуры одно-,
а не безадресные.
Стеки привлекательны, во-первых, тем, что не нуждающиеся в операндах команды
могут иметь очень короткий код операции (как правило, достаточно одного
байта) и, во-вторых, тем, что работающая с ними программа представляет
собой арифметическое выражение, записанное в обратной польской нотации
— когда мы сначала пишем операнды, а потом знак операции. Например, операция
а+ь в этой записи выглядит как ab+
(в программе — push a; push b; add;).
Задача преобразования привычных нам арифметических выражений в обратную
польскую запись легко формализуется, поэтому стековые процессоры долгое
время позиционировались как "ориентированные на языки высокого уровня".
Позже, впрочем, выяснилось, что более сложная логика разбора арифметических
выражений позволяет проводить разного рода оптимизации (сокращать введенные
лишь для удобства записи переменные, заменять выражения, которые всегда
дают одно и то же значение, на константы, выносить повторяющиеся вычисления
из тела цикла и т. д.).
Аппаратно реализованные стековые архитектуры — в наше время редкость.
Из относительно современных процессоров, имевших коммерческий успех, можно
назвать Transputer фирмы Inmos (в настоящее время эти микропроцессоры
выпускаются фирмой SGC-Thomson).
Шире всего стековая архитектура распространена в
байт-кодах или, как это еще называют, системах команд виртуальных
машин. Байт-код - это промежуточное представление программы, используемое
интерпретатором, чтобы избежать лексического и синтаксического анализа
программы на этапе исполнения. Исполнение байт-кода осуществляется не
процессором, а программой-интерпретатором. Таким образом, реализуются
многие современные языки программирования — многочисленные диалекты языка
BASIC, Lisp, SmallTalk, Fort (этот язык любопытен тем, что сам имеет стековый
синтаксис), наконец Java. Некоторые реализации интерпретаторов этих языков
используют так называемую JIT-комтшяцию (Just In Time, точно в момент
[исполнения]), когда перед исполнением байт-код компилируется в систему
команд физического процессора. Такая технология позволяет достичь для
"интерпретируемых" программ производительности, не уступающей
производительности компилированного кода.
Первым промышленным применением JIT-компиляции была система AS/400 фирмы
IBM. В настоящее время JIT широко используется в реати-зациях Java. JIT-компиляция
привлекательна тем, что позволяет исполнять один и тот же код на разнообразных
процессорах без потерь (или почти без потерь) скорости.
|