Работа большинства ЭВМ сопряжена с передачей данных и управляющей информации между процессором и памятью. Обычно программируемая управляющая информация называется машинным языком. Для того чтобы выполнить некоторую программу, данная программа должна быть представлена на машинном языке используемой ЭВМ. С развитием вычислительной техники машинные языки стали весьма сложными и трудными для освоения программистом. Вследствие этого были созданы языки ассемблера и языки высокого уровня, которые затем транслируются на машинный язык. Среди различных языков, поддерживаемых вычислительными системами, наиболее близок к машинному языку язык ассемблера. Поэтому для должного понимания языка ассемблера необходимо понимание машинного языка, на который транслируется программа, написанная на языке ассемблера. В данной главе описываются основы организации ЭВМ семейства VAX, процессор, память, а также то, как осуществляется управление некоторыми основными операциями с помощью машинного языка.
На рис. 3.1 показаны важнейшие части простой цифровой ЭВМ: устройство ввода, устройство вывода, память и центральное устройство управления, или процессор. Устройство ввода позволяет вводить информацию в ЭВМ. К простым устройствам ввода относятся кнопки или клавиши электронного калькулятора либо клавиатура, подобная клавиатуре пишущей машинки. Устройство вывода позволяет получить обратно результаты работы ЭВМ. В число простых устройств вывода входят цифровые индикаторы электронного калькулятора, подобные пишущей машинке печатающие устройства, а также экран видеотерминала. Память используется для запоминания информации. В общем случае память может быть представлена как множество ячеек, каждая из которых содержит некоторое число. (Кроме основной памяти большинство ЭВМ для хранения дополнительной информации имеет внешние запоминающие устройства, такие как магнитные диски.) Устройство ввода, устройство вывода и память соединяются электрическими проводниками с центральным устройством управления, называемым процессором. Процессор, посылая по этим проводникам электрические сигналы, может:
Рис. 3.1. Структура ЭВМ
В этой простой ЭВМ устройство ввода, устройство вывода и память являются пассивными устройствами. Они не выполняют никаких действий до тех пор, пока не получат указание процессора выполнить какую-либо операцию. Процессор представляет собой активное устройство, управляющее обменом информацией между ним самим и другими устройствами. Последовательность операций, выполняемых процессором, определяется множеством инструкций, которые образуют машинную программу. Работа программиста заключается в том, чтобы составить соответствующую последовательность инструкций, указывающих процессору, какие операции необходимо выполнить для решения конкретной задачи.
Память ЭВМ семейства VAX можно рассматривать как набор ячеек памяти, каждая из которых содержит 8-битовый байт. Поэтому назовём содержимое такой ячейки байтом памяти или просто байтом. Байт в ячейке памяти обычно можно представить двумя шестнадцатеричными цифрами (от ^X00 до ^XFF).
Каждая ячейка памяти идентифицируется числом, называемым адресом ячейки памяти. Он позволяет однозначно идентифицировать ячейку. По аналогии адрес ячейки памяти можно представить себе как адрес дома на улице. И так же, как по адресу дома на улице можно найти или идентифицировать конкретное здание, адрес памяти позволяет найти или идентифицировать определённую ячейку памяти.
В ЭВМ семейства VAX адресом является 32-битовое двоичное целое число. Обычно 32-битовые адреса представляются восемью шестнадцатеричными цифрами. Например, предположим, что по адресу ^X00ABCDEF содержится байт ^X35. В шестнадцатеричном представлении это выглядит следующим образом:
Шестнадцатеричное содержимое |
Шестнадцатеричный адрес |
---|---|
35 |
00ABCDEF |
Здесь адрес показан справа, а содержимое показано слева потому, что таким образом располагает информацию ассемблер ЭВМ VAX. Причины этого будут выявлены позже. Обратите внимание, что с каждым байтом памяти связываются два числа - адрес (32-битовое число) и содержимое (8-битовое число).
Поскольку в 32 двоичных разрядах могут быть образованы 232, или 4 292 967 296, двоичные комбинации, то в программе для ЭВМ семейства VAX можно было бы адресовать до 4 294 967 296 различных байтов памяти (приблизительно 5 млрд, байтов, или 4 Гбайта). Первый байт памяти имеет адрес ^X00000000, а последний - адрес ^XFFFFFFFF. На рис. 3.2 показано возможное содержимое первых 11 байтов памяти.
Шестнадца- теричное содержимое |
Шестнадца- теричный адрес |
---|---|
90 |
00000000 |
9F |
00000001 |
34 |
00000002 |
12 |
00000003 |
00 |
00000004 |
00 |
00000005 |
9F |
00000006 |
EF |
00000007 |
CD |
00000008 |
0В |
00000009 |
00 |
0000000А |
Рис. 3.2. Пример шестнадцатеричного представления содержимого памяти
Как было показано в гл. 2, ЭВМ семейства VAX кроме байтов работают со словами, длинными словами и квадрасловами. В памяти ЭВМ 16-битовое слово запоминается в двух смежных байтах. В следующем примере показано, как слово ^X1234 можно запомнить в байтах памяти с адресами ^X00000002 и ^X00000003.
Шестнадцатеричное содержимое | Шестнадцатеричный адрес |
---|---|
34 |
00000002 |
12 |
00000003 |
Отметим, что здесь представлено слово ^X1234, а не слово ^X3412. В ЭВМ семейства VAX младшие разряды слова, в данном случае имеющие шестнадцатеричное представление ^X34, запоминаются в байте с младшим адресом ^X00000002, а старшие разряды слова ^X12 - в байте со старшим адресом ^X00000003. При таком представлении слов байты слова нужно читать сверху вниз. Чтобы избежать этого, распечатки данных для ЭВМ семейства VAX обычно читаются справа налево. Поэтому слова в памяти часто представляются следующим образом:
Шестнадцатеричное содержимое |
Шестнадцатеричный адрес |
---|---|
1234 |
00000002 |
Здесь указывается только один адрес, однако при этом понимается, что в байте памяти с адресом ^X00000002 содержится ^X34, а в байте с адресом ^X00000003 содержится ^X12. Для напоминания программистам о возможном расположении информации в нескольких байтах такие программы, как ассемблер, располагают адрес справа от содержимого.
В памяти ЭВМ 32-битовые длинные слова запоминаются в четырёх смежных байтах. В следующем примере показано, как может быть запомнено в памяти длинное слово ^X000BCDEF, начиная с адреса ^X00000007.
Шестнадцатеричное содержимое | Шестнадцатеричный адрес |
---|---|
EF |
00000007 |
CD |
00000008 |
0В |
00000009 |
00 |
0000000А |
Отметим, что здесь снова необходимо читать байты длинного слова снизу вверх. Содержимым длинного слова, начинающегося с адреса ^X00000007, является ^X000BCDEF, а не ^XEFCD0B00. Чтобы устранить это неудобство, длинные слова в памяти часто представляются в следующем виде:
Шестнадцатеричное содержимое | Шестнадцатеричный адрес |
---|---|
000BCDEF |
00000007 |
Программист должен помнить, что в данном случае длинное слово в действительности занимает байты с адресами от ^X00000007 до ^X0000000A, а младшие разряды длинного слова ^XEF содержатся в байте с адресом ^X00000007.
Квадраслово (64 бита) запоминается в памяти в восьми смежных байтах. А ещё большая единица информации - 128-битовое октаслово запоминается в памяти в шестнадцати смежных байтах.
Предположим, что в 11 байтах, показанных на рис. 3.2, представлены три байта, два слова и одно длинное слово в следующем порядке:
Шестнадцатеричное содержимое |
Шестнадцатеричный адрес |
---|---|
90 |
00000000 |
9F |
00000001 |
1234 |
00000002 |
0000 |
00000004 |
9F |
00000006 |
000BCDEF |
00000007 |
Рис. 3.3. Компактное представление содержимого памяти
Содержимое памяти, показанное на рис. 3.2, может быть представлено и более компактно, как показано на рис. 3.3. Далее в основном будет использоваться такое представление. Однако важно понимать, что на рис. 3.2 и 3.3 изображена одна и та же информация, которая является просто различным представлением одного и того же содержимого памяти. Рассматривая рис. 3.3, можно предположить, что содержимое ^X9F байта памяти с адресом ^X00000006 будет обрабатываться как байт. Тем не менее вполне возможно, что в один момент времени программа будет обрабатывать содержимое данного байта памяти как байт, в другой момент времени - как часть слова, а в последующее время - как часть длинного слова. Не существует способа, который позволил бы, посмотрев на байт в памяти, определить, как он будет использоваться.
Очень важно не путать адрес байта, слова и длинного слова с содержимым байта, слова и длинного слова. В частности, это может происходить при работе с длинными словами, так как длина адреса памяти и длина длинного слова совпадают и равны 32 бита. Например, ниже показаны длинные слова, расположенные в памяти, начиная с адреса ^X00001000.
Шестнадцатеричное содержимое | Шестнадцатеричный адрес |
---|---|
00001234 |
00001000 |
A3B4F303 |
00001004 |
00001000 |
00001008 |
00000000 |
0000100C |
........ |
00001010 |
Во второй строке начальным адресом длинного слова является ^X00001004, а его содержимым является ^XA3B4F303. Возможно изменить содержимое ячейки памяти, но нельзя изменить её адрес. Иначе говоря, если содержимое ячейки памяти представляет собой переменную величину, то адрес ячейки памяти фиксирован.
Различие между адресом ячейки памяти и её содержимым усложняет то обстоятельство, что содержимым одной ячейки памяти часто является адрес другой ячейки памяти. Например, содержимое длинного слова ^X00001000, расположенного по адресу ^X00001008, само может быть адресом ^X00001000. В этом случае говорят, что содержимое длинного слова с адресом ^X00001008 указывает на длинное слово ^X00001234 с адресом ^X00001000.
Использование таких указателей весьма распространено и крайне важно. Если программа должна выполнять обработку объектов, расположенных в памяти, то ей должны быть доступны адреса этих объектов и эти адреса вместе с машинной программой должны присутствовать в памяти. Более того, указатели и адреса составляют основу для построения многих структур данных. Путаница между адресом ячейки памяти и содержимым ячейки памяти представляет собой одну из наиболее общих ошибок при написании программ на языке ассемблера.
Память ЭВМ работает под управлением процессора. Процессор может либо запросить память произвести выборку байта из определённой ячейки памяти, либо осуществить запись отдельного байта в определённую ячейку памяти. Операция выборки не изменяет, а операция записи изменяет содержимое указываемой ячейки памяти. Для того чтобы произвести выборку, процессор посылает устройству памяти адрес требуемой ячейки памяти, а устройство памяти отвечает на запрос процессора, посылая ему содержимое адресуемой ячейки. Например, воспользуемся данными, приведёнными на рис. 3.3. Если процессор выдал запрос устройству памяти на выборку байта из ячейки памяти с адресом ^X00000006, то устройство памяти отвечает на запрос, посылая процессору число ^X9F. Содержимым ячейки памяти с адресом ^X00000006 останется число ^X9F.
Для выполнения операции записи процессор посылает устройству памяти адрес требуемой ячейки памяти вместе с числом, которое должно быть помещено в указываемую ячейку. Снова воспользуемся данными, приведёнными на рис. 3.3. Предположим, что процессор запросил устройство памяти выполнить запись байта ^X1B в ячейку памяти с адресом ^X00000006. Старое содержимое ячейки памяти с адресом ^X00000006 будет потеряно или уничтожено, а её новым содержимым будет ^X1B. При этом не останется никакой записи о том, что в ячейке памяти с адресом ^X00000006 когда-либо содержалось ^X9F. Если бы впоследствии процессор выдал устройству памяти запрос на выборку байта из ячейки памяти с адресом ^X00000006, то устройством памяти в ответ на запрос было бы передано новое содержимое этой ячейки ^X1B.
Операции выборки и записи, производимые над более крупными порциями информации, такими как слова и длинные слова, выполняются аналогично. Воспользуясь данными, приведёнными на рис. 3.3, предположим, что процессор запрашивает устройство памяти, чтобы осуществить выборку содержимого слова, начинающегося с адреса ^X00000002. Устройство памяти отвечает на запрос, посылая процессору содержимое байта ^X34, расположенного по адресу ^X00000002, а также содержимое байта ^X12 с адресом ^X00000003. Процессор объединяет эти два байта, чтобы образовать слово ^X1234. Аналогично если процессор запрашивает устройство памяти для выполнения выборки длинного слова, начинающегося с адреса ^X00000007, то устройство памяти отвечает, посылая процессору содержимое байтов с адресами ^X00000007, ^X00000008, ^X00000009 и ^X0000000A. Процессор из этих четырёх байтов формирует длинное слово ^X000BCDEF. Если бы процессор выдал запрос устройству памяти на выборку длинного слова, начинающего с адреса ^X00000004, то устройство памяти в ответ на запрос послало бы процессору четыре байта, расположенные в памяти по адресам с ^X00000004 до ^X00000007, которые после этого были бы собраны процессором в длинное слово ^XEF9F0000[1].
Выборка и запись являются единственными операциями, которые может выполнять устройство памяти. Например, устройство памяти не может выполнить сложение. Если желательно сложить два числа, находящиеся в памяти, то оба эти числа должны быть выбраны из памяти и переданы процессору, а после сложения полученный результат снова должен быть записан в память.
Как уже упоминалось, процессор является активным устройством, управляющим передачей данных между ним самим и другими устройствами, входящими в состав ЭВМ, такими, как, например, память. В свою очередь, программист управляет процессором с помощью написанной им последовательности инструкций, называемой программой, которая выполняется процессором. Например, приведённая ниже инструкция заставит процессор выполнить сложение байта, расположенного в ячейке памяти с адресом ^X00001001, с байтом, содержащимся в ячейке памяти с адресом ^X00001003, а 8-битовый результат поместить в ячейку памяти с адресом ^X00001003.
ADDB2 ^X00001001,^X00001003
Отметим, что эта инструкция не заставляет процессор выполнять сложение чисел ^X00001001 и ^X00001003, что в результате даёт число ^X00002004. Вместо этого инструкция даёт указание процессору сложить содержимое байтов памяти с адресами ^X00001001 и ^X00001003. а их сумму поместить в байт памяти с адресом ^X00001003. Эта инструкция выполняется процессором за четыре шага.
Шаг 1. Выбрать байт из ячейки памяти с адресом ^X00001001.
Шаг 2. Выбрать байт из ячейки памяти с адресом ^X00001003.
Шаг 3. Сложить байты, выбранные на шаге 1 и шаге 2.
Шаг 4. Запомнить полученную сумму в ячейке памяти с адресом ^X00001003.
Байты с адресами ^X00001001 и ^X00001003 называются операндами, так как они являются теми объектами, над которыми выполняется операция сложения по инструкции ADDB2.
Инструкции SUBB2 (SUBtract Byte - вычесть байт, два операнда) и MOVB (MOVe Byte - переслать байт) подобны инструкции ADDB2 (ADD Byte - сложить байты, два операнда). Чтобы выполнить инструкцию.
SUBB2 ^X00001FFF,^X00000500
процессор совершает такую последовательность действий:
Шаг 1. Выбирает байт из ячейки памяти с адресом ^X00001FFF.
Шаг 2. Выбирает байт из ячейки памяти с адресом ^X00000500.
Шаг 3. Вычитает байт, выбранный на шаге 1, из байта, выбранного на шаге 2.
Шаг 4. Запоминает полученную разность в ячейке памяти с адресом ^X00000500.
Для выполнения инструкции
MOVB ^X00001000,^X00001003
процессор совершает два следующих действия:
Шаг 1. Выбирает байт из ячейки памяти с адресом ^X00001000
Шаг 2. Запоминает выбранный на шаге 1 байт в ячейке памяти с адресом ^X00001003.
Программа представляет собой просто последовательность инструкций. Например, в результате выполнения программы, приведённой на рис. 3.4, содержимое байта памяти с адресом ^X00001003 станет равным сумме байтов с адресами ^X00001000, ^X00001001 и ^X00001002.
ИНСТРУКЦИЯ 1 |
MOVB |
^X00001000, ^X00001003 |
ИНСТРУКЦИЯ 2 |
ADDB2 |
^X00001001, ^X00001003 |
ИНСТРУКЦИЯ 3 |
ADDB2 |
^X00001002, ^X00001003 |
ИНСТРУКЦИЯ 4 |
RET |
|
Рис. 3.4. Пример простой программы
Приведённые на рис. 3.4 инструкции процессор выполняет последовательно одну за другой. По инструкции RET (сокращение от RETurn - возврат) управление процессором из текущей программы возвращается программе, инициировавшей выполнение текущей программы. Если текущая программа является основной программой, запущенной на выполнение из операционной системы VAX/VMS, то по инструкции RET управление процессором будет возвращено ОС VAX/VMS.
Например, предположим, что в памяти первоначально содержится следующая информация:
Содержимое | Адрес |
---|---|
1А |
00001000 |
26 |
00001001 |
05 |
00001002 |
?? |
00001003 |
Два вопросительных знака означают, что не надо заботиться (или знать) о первоначальном содержимом байта с адресом ^X00001003. По первой инструкции программы, приведённой на рис. 3.4, произойдёт пересылка значения ^X1A в байт с адресом ^X00001003; по второй инструкции выполнится сложение значения ^X26 с содержимым байта с адресом ^X00001003, после чего его содержимое изменится и станет равно ^X1A + ^X26, или ^X40; по третьей инструкции сложение со значением ^X05 изменит содержимое байта с адресом ^X00001003, которое станет равно ^X40 + ^X05, или ^X45. Когда этой программой будет возвращено управление, содержимое памяти будет следующим:
Содержимое | Адрес |
---|---|
1А |
00001000 |
26 |
00001001 |
05 |
00001002 |
45 |
00001003 |
Теперь вполне резонно возникает вопрос: "Где в ЭВМ хранится программа?" В приведённом ранее описании было названо одно место, в котором может содержаться информация, - память. Поэтому память может быть использована для хранения программ. Однако так как в ячейках памяти информация может храниться только в двоичном виде, то конкретные инструкции процессора должны быть закодированы в двоичном коде. В следующей таблице приведены коды операций инструкций MOVB, ADDB2, SUBB2 и RET; каждое двухзначное шестнадцатеричное число обозначает 8-битовый двоичный код операции:
Мнемоника | Код операции |
---|---|
MOVB |
90 |
ADDB2 |
80 |
SUBB2 |
82 |
RET |
04 |
Кроме кода операции в инструкциях ЭВМ VAX присутствуют спецификаторы операндов, которые указывают, как могут быть найдены операнды (в данном случае - пересылаемые, складываемые или вычитаемые байты). Простейший способ обозначить операнд - это задать его 32-битовый адрес (он уже применялся в данной главе). Такой способ нахождения операнда называется абсолютной адресацией. Для обозначения абсолютной адресации используется код или спецификатор операнда 9F.
В следующем примере в шестнадцатеричном представлении показано, как кодируется инструкция MOVB:
90 9F 00001000 9F 00001003
Код операции 90 определяет инструкцию MOVB. Спецификатор первого операнда 9F указывает, что будет задан 32-битовый адрес операнда, а ^X00001000 является этим адресом. Спецификатор второго операнда 9F указывает, что и второй операнд задаётся 32-битовым адресом, затем следует адрес ^X00001003. Если данная инструкция размещена в памяти с адреса ^X00001004, то это выглядит следующим образом:
Примечание | Содержимое | Адрес |
---|---|---|
Код операции MOVB |
90 |
00001004 |
Спецификатор операнда |
9F |
00001005 |
Адрес, по которому выбирается байт |
00001000 |
00001006 |
Спецификатор операнда |
9F |
0000100А |
Адрес, по которому заносится байт |
00001003 |
0000100В |
Инструкции в таком полностью числовом формате называются инструкциями на машинном языке или в машинном коде. Обратите внимание, что, когда инструкция MOVB кодируется в машинном коде, она занимает 11 байтов памяти. Код операции занимает 1 байт, а также требуется по 5 байтов для определения месторасположения каждого из двух операндов - 1 байт для спецификатора операнда и 4 байта для 32-битового адреса.
Более компактно приведённая выше инструкция MOVB может быть записана следующим образом:
Содержимое памяти | Адрес |
---|---|
00001003 9F 00001000 9F 90 |
00001004 |
Инструкцию в таком формате следует читать справа налево. Адрес начала инструкции ^X00001004 помещается в конце строки. Слева от адреса расположена информация, обозначающая содержимое памяти в диапазоне адресов от ^X00001004 до ^X0000100E. После адреса начала инструкции в строке в последовательности справа налево находятся: код операции ^X90, спецификатор первого операнда байт ^X9F, адрес ^X00001000, по которому выбирается пересылаемый байт, спецификатор второго операнда байт ^X9F и адрес ^X00001003, по которому заносится в память пересылаемый байт. Далее в книге обычно будет использоваться именно такое представление для инструкций в машинном коде. Отметьте, что два приведённых представления инструкции MOVB содержат одинаковую информацию о содержимом памяти. Единственным различием является их формат.
Инструкции ADDB2 и SUBB2 имеют одинаковый формат с инструкцией MOVB и различаются только кодами операций. В противоположность этому инструкция RET занимает только 1 байт памяти, так как она не имеет никаких операндов. На рис. 3.5 показано, как будет выглядеть в машинном коде программа, приведённая на рис. 3.4.
Примечания | Содержимое | Адрес | ||
---|---|---|---|---|
БАЙТ ДАННЫХ |
|
|
1А |
00001000 |
БАЙТ ДАННЫХ |
|
|
26 |
00001001 |
БАЙТ ДАННЫХ |
|
|
05 |
00001002 |
РЕЗУЛЬТАТ (СУММА) |
|
|
?? |
00001003 |
MOVB ИНСТРУКЦИЯ |
00001003 9F |
00001000 9F |
90 |
00001004 |
ADDB2 ИНСТРУКЦИЯ |
00001003 9F |
00001001 9F |
80 |
0000100F |
ADDB2 ИНСТРУКЦИЯ |
00001003 9F |
00001002 9F |
80 |
0000101А |
RET ИНСТРУКЦИЯ |
|
|
04 |
00001025 |
Рис. 3.5. Стандартный формат программы в машинном коде
При выполнении инструкций с адреса ^X00001004 процессор:
В результате этого в байт памяти с адресом ^X00001003 было бы помещено значение ^X45.
В предыдущем разделе было описано, как числа, включая данные и инструкции на машинном языке, хранятся в памяти. В дополнение к основной памяти непосредственно сам процессор ЭВМ VAX содержит небольшое количество памяти с очень быстрым доступом. Чтобы отличить эти довольно ограниченные внутренние запоминающие ячейки процессора от существенно большей области основной памяти, внутренние запоминающие ячейки процессора называются регистрами процессора или просто регистрами.
Хотя в процессоре ЭВМ VAX существуют разнообразные внутренние запоминающие ячейки, большинство программистов в основном имеют дело с 16 регистрами, называемыми регистрами общего назначения (сокращённо РОН). Поскольку все 16 регистров общего назначения являются 32-разрядными, то в каждый регистр помещается длинное слово (четыре байта). Чтобы различать между собой регистры общего назначения, им присвоены номера от 0 до 15 (десятичные числа) или от ^X0 до ^XF (шестнадцатеричные числа). Обратите внимание, что эти регистры сильно отличаются от ячеек памяти. Каждая минимальная адресуемая ячейка памяти может содержать только один байт (восемь битов информации). Если в память помещается 32-битовое длинное слово, то для него требуется четыре таких ячейки памяти. В противоположность этому в каждый регистр общего назначения помещается длинное слово, так что в 16 регистрах общего назначения всего размещаются 16 длинных слов, или 64 байта.
Вопреки своему названию регистр общего назначения 15 используется для весьма определённой цели. (Как мы увидим далее, регистры общего назначения 12, 13 и 14 также применяются для определённых целей.) При выполнении процессором каждой инструкции на машинном языке он использует регистр 15 для адресации следующей инструкции. Вследствие этого регистр процессора 15 называется программным счётчиком (Program Counter) или просто PC. Чтобы понять, как работает программный счётчик, ниже показаны первые 15 байтов программы, приведённой на рис. 3.5.
Память | ||
---|---|---|
Содержимое | Адрес | Процессор |
1А |
00001000 |
00001004 PC |
26 |
00001001 |
|
05 |
00001002 |
|
?? |
00001003 |
|
90 |
00001004 |
|
9F |
00001005 |
|
00 |
00001006 |
|
10 |
00001007 |
|
00 |
00001008 |
|
00 |
00001009 |
|
9F |
0000100А |
|
03 |
0000100В |
|
10 |
0000100С |
|
00 |
0000100D |
|
00 |
0000100Е |
|
... |
0000100F |
|
Для того чтобы выполнить программу, начинающуюся с адреса ^X00001004, необходимо поместить адрес ^X00001004 в программный счётчик PC, как показано выше. Такая загрузка адреса производится ОС VAX/VMS при передаче ею управления программе на машинном языке. После этого процессор выполняет инструкцию MOVB, начинающуюся с адреса ^X00001004, для чего он должен совершить следующие действия.
Шаг 1. Выбрать 8-битовый код операции. Так как программный счётчик содержит значение ^X00001004, процессор произведёт выборку байта ^X90, расположенного по адресу ^X00001004, считая, что данный байт является кодом операции. Кроме того, процессор увеличит содержимое программного счётчика на 1, так что теперь программный счётчик будет содержать значение ^X00001005 (в этом случае говорят, что программный счётчик указывает на адрес ^X00001005).
Шаг 2. Выбрать байт спецификатора операнда. Так как выбранный на шаге 1 код операции является кодом операции инструкции MOVB, то вслед за этим процессор производит выборку байта ^X9F, на который в текущий момент времени указывает регистр PC. Процессор считает, что данный байт является спецификатором операнда. Содержимое программного счётчика увеличивается на 1, после чего программный счётчик указывает на адрес ^X00001006.
Шаг 3. Выбрать адрес первого операнда. Выбранный на шаге 2 байт спецификатора операнда ^X9F показывает, что программный счётчик указывает на адрес операнда. Иначе говоря, следующие после байта спецификатора операнда четыре байта представляют собой адрес операнда. Процессор производит выборку четырёх байтов с адресами от ^X00001006 до ^X00001009 и собирает эти байты, чтобы сформировать адрес ^X00001000. Одновременно с этим содержимое программного счётчика увеличивается на 4, так что он указывает теперь на адрес ^X0000100A.
Шаг 4. Выбрать первый операнд. Так как на шаге 3 был выбран адрес нахождения операнда ^X00001000, то процессор производит выборку байта ^X1A, расположенного по этому адресу.
Шаг 5. Выбрать байт спецификатора второго операнда. Поскольку в инструкции MOVB требуется два операнда, то процессор производит выборку байта ^X9F, на который указывает регистр PC, содержащий адрес ^X0000100A, и интерпретирует этот байт как байт спецификатора операнда. Процессор также увеличивает на 1 содержимое регистра PC, которое становится равным ^X0000100B.
Шаг 6. Выбрать адрес второго операнда. Так как на шаге 5 был выбран код ^X9F, то процессор производит выборку содержимого байтов с адресами от ^X0000100B до ^X0000100E и, объединяя их вместе, формирует адрес ^X00001003. Кроме того, содержимое регистра PC увеличивается на 4. Регистр PC содержит теперь адрес ^X0000100F.
Шаг 7. Выполнить пересылку. Процессор помещает байт ^X1A, выбранный на шаге 4, по адресу ^X00001003, выбранному на шаге 6. Этим завершается выполнение инструкции MOVB. Содержимым регистра PC остаётся ^X0000100F, так как на текущем шаге содержимое регистра не модифицировалось.
После завершения выполнения инструкции процессор производит выборку байта, указываемого программным счётчиком, и увеличивает содержимое регистра PC, считая, что данный байт является новым кодом операции. (После завершения шага 7 приведённой выше последовательности действий процессор будет производить выборку содержимого памяти с адресом ^X0000100F, считая, что это новый код операции.) Последовательность действий, которую затем выполняет процессор, зависит от нового кода операции. Если код операции соответствует инструкции MOVB, то процессор выполнит предыдущие семь шагов; если новый код операции задаёт инструкцию ADDB2 или SUBB2, процессор выполнит последовательность действий, состоящую из девяти шагов. Первые шесть шагов идентичны первым шести шагам выполнения инструкции MOVB, показанным выше. Остальные три шага приводятся ниже.
Шаг 7. Выбрать второй операнд. Процессор производит выборку байта, используя адрес, полученный на шаге 6.
Шаг 8. Выполнить сложение или вычитание. Процессор складывает (или вычитает) байт, выбранный на шаге 4, с байтом (из байта), выбранным на шаге 7.
Шаг 9. Запомнить результат. Процессор помещает вычисленное на шаге 8 значение в байт памяти, расположенный по адресу, который был выбран на шаге 6.
Выполняя программу, процессор слепо выбирает из памяти и выполняет инструкции на машинном языке до тех пор, пока: 1) не будет встречена инструкция RET, 2) оператор сам (вручную) не остановит ЭВМ или 3) некоторое состояние ошибки не заставит процессор завершить выполнение программы.
Как мы только что видели, содержимое байта памяти можно интерпретировать или использовать различными способами. Например, на рис. 3.5 некоторые байты трактовались как коды операций, другие - как спецификаторы операндов, третьи - как байты, составляющие 4-байтовый адрес, а прочие рассматривались как операнды. Невозможно посмотреть содержимое байта памяти и определить, как следует интерпретировать это содержимое. Если в каком-либо конкретном байте памяти содержится код ^X9F, то это содержимое может быть:
Важно отличать друг от друга коды операций, спецификаторы операндов, адреса и операнды, так как каждому из них отводится различная роль. Код операции даёт указание процессору совершить некоторую операцию, такую как MOVB, ADDB2, SUBB2 или RET. Поскольку каждый код операции является 8-битовым, то потенциально имеется 28, или 256, различных кодов операции[2]. В программах пользователей может использоваться большинство допустимых кодов операций. Однако некоторые коды операций, включая инструкцию HALT (остановить) с кодом операции ^X00, относятся к привилегированным инструкциям и могут выполняться только теми компонентами операционной системы, которые имеют особые привилегии. Если в программе пользователя предпринимается попытка выполнить привилегированную инструкцию, то возникнет ошибка, называемая прерыванием по резервной инструкции (reserved instruction trap), и управление будет возвращено ОС VAX/VMS.
Байт спецификатора операнда указывает способ определения местонахождения операнда. Поскольку спецификатор операнда занимает восемь битов (один байт), то потенциально существует 28, или 256, различных способов определения местонахождения операнда. До сих пор рассматривался единственный спецификатор операнда - код ^X9F. Это значение спецификатора операнда указывает, что после байта спецификатора операнда непосредственно следует длинное слово адреса операнда. Как было отмечено ранее, такой способ определения местонахождения операнда называется абсолютной адресацией. Некоторые из других 255 возможных значений байта - спецификатора операнда являются недопустимыми. Попытка использования недопустимого значения вызовет прерывание по резервному режиму адресации (reserved addressing mode fault), по которому управление будет возвращено ОС VAX/VMS.
Адреса представляют собой 32-битовые длинные слова, значение адреса может изменяться от ^X00000000 до ^XFFFFFFFF. Однако операционная система VAX/VMS обычно ограничивает диапазон адресов, к которым может иметь доступ программа пользователя. Попытка нарушить эти ограничения приводит к ошибке, называемой прерыванием по нарушению контроля доступа (access control violation fault).
Для байтового операнда допустимо любое шестнадцатеричное значение от ^X00 до ^XFF. Как было отмечено в гл. 2, в формате байта могут быть представлены числа со знаком и без знака. Важно понять, что имеется только одна инструкция сложения байтов - ADDB2. Например, при сложении байтов ^XFC и ^X02 результат будет равен ^XFE. Если эти значения интерпретировать как числа без знака, то их сложение будет соответствовать сложению десятичных чисел 252 и 2, что даст в результате 254. При интерпретации этих значений как чисел со знаком их сложение соответствует сложению чисел -4 и 2, что в сумме даст -2.
Ошибки переполнения возможны при любой интерпретации чисел. Например, сумма ^XFF и ^X03 равна ^X02. (В обычных условиях правильной суммой является ^X102, но это число не помещается в формате байта.) Для чисел со знаком такой результат корректен, так как сумма чисел -1 и 3 равна 2. Однако в случае чисел без знака результат неверен, так как сумма чисел 255 и 3, конечно, не равна 2. Тогда говорят, что произошло переполнение числа без знака. На ЭВМ семейства VAX переполнение числа без знака не рассматривается как ошибка. В гл. 6 объясняется, как проводится проверка на переполнение беззнаковых чисел.
Аналогично сумма ^X7E и ^X04 равна ^X82. В этом случае для чисел без знака результат будет правильным (126 плюс 4 равно 130), но для чисел со знаком он неверен (126 плюс 4 не равно -126). Тогда говорят, что произошло переполнение числа со знаком. Если в специальный разряд процессора, называемый битом IV, занесена 1, то при переполнении числа со знаком будет порождаться ошибка, называемая прерыванием по арифметической операции (arithmetic trap). В противном случае ошибка не возникает. В гл. 6 показано также, как программист может проверить наличие ошибки переполнения числа со знаком.
Как отмечалось ранее, помимо байтовых операндов ЭВМ семейства VAX могут работать с операндами в формате 16-битового слова, 32-битового длинного слова и в некоторых случаях - с операндами в формате 64-битового квадраслова. При выполнении арифметических операций над операндами в формате слова или длинного слова может происходить переполнение чисел со знаком и без знака, точно так же как и при выполнении операций над байтами.
Содержимое | Адрес |
---|---|
1F |
00000200 |
05 |
00000201 |
FF |
00000202 |
3F |
00000203 |
Опишите, что произойдёт при выполнении нижеследующих инструкций на машинном языке. Для каждой инструкции выпишите адрес и новое содержимое каждого байта, если оно изменилось. (Считайте, что инструкции выполняются независимо друг от друга. Перед выполнением каждой инструкции содержимое байтов памяти с адресами от ^X0200 до ^X0203 имеет начальные значения, приведённые выше) :
а) | 00000203 |
9F |
00000200 |
9F |
90; |
б) | 00000201 |
9F |
00000200 |
9F |
80; |
в) | 00000202 |
9F |
00000200 |
9F |
80; |
г) | 00000200 |
9F |
00000201 |
9F |
82; |
д) | 00000203 |
9F |
00000203 |
9F |
82. |
Для описания инструкций ЭВМ семейства VAX будут применяться условные обозначения, подобные обозначениям, используемым фирмой Digital Equipment Corporation в документации для вычислительных систем VAX. Например, описание четырёх инструкций, с которыми читатель уже знаком, выглядит следующим образом:
Мнемоника | Код операции | Операнды | Операция (описание) |
---|---|---|---|
ADDB2 |
80 |
add, sum |
sum ← sum + add |
SUBB2 |
82 |
sub, dif |
dif ← dif - sub |
MOVB |
90 |
src, dst |
dst ← src |
RET |
04 |
|
возврат управления |
В первой строке дано описание инструкции ADDB2. Мнемонический код операции ADDB2 обозначает инструкцию сложения байтов (Add Byte) с двумя операндами. В графе "Код операции" указывается код операции ^X80, соответствующий инструкции ADDB2. Обозначения add (слагаемое) и sum (сумма) в поле операндов могут рассматриваться как имена переменных в языках высокого уровня, таких как Фортран и Паскаль. Данные обозначения используются также в графе описания действия операции "Операция". В этой графе описание sum ← sum + add показывает, что первый операнд, обозначенный add, складывается со вторым операндом sum, а результат сложения помещается в sum - во второй операнд.
Другие инструкции описываются аналогично. Для инструкции SUBB2 (Subtract Byte - вычесть байт, два операнда) описанием операции является dif ← dif - sub. Это означает, что по месту нахождения второго операнда dif (разность) помещается разность между первоначальным значением второго операнда dif и значением первого операнда sub (вычитаемое). В описании инструкции MOVB обозначение src (от SouRCe - источник) относится к тому операнду, который будет выбираться или считываться из памяти, а обозначение dst (от DeSTination - место назначения или получатель) относится к операнду, по месту нахождения которого будет занесён или записан в память результат.
Следует сделать два замечания относительно такого описания инструкций. Во-первых, описания следует читать в обычном порядке - слева направо, в отличие от кодов машинного языка, которые читаются справа налево. Во-вторых, такой формат описания использовался при описании инструкций ЭВМ семейства VAX, приведённых на развороте обложки и в приложении Е.
На примере инструкции сложения будет проиллюстрировано, как из отдельных инструкций образуется семейство инструкций. В гл. 1 рассматривалась инструкция ADDL2 (ADD Longword - сложить длинное слово, два операнда). Семейство инструкций сложения ADD включает инструкции сложения операндов в формате байта и слова. Описание инструкций сложения дано ниже.
Мнемоника | Код операции | Операнды | Операция |
---|---|---|---|
ADDB2 |
80 |
add, sum |
sum ← sum + add |
ADDW2 |
А0 |
||
ADDL2 |
С0 |
Эти инструкции будут называться семейством инструкций ADD2.
В гл. 1 рассматривалась также инструкция ADDL3 (ADD Longword - сложить длинное слово, три операнда). Семейство инструкций сложения ADD включает также инструкции с тремя операндами, в том числе инструкции сложения операндов в формате байта и слова. Описание семейства инструкций ADD3 приведено ниже.
Мнемоника | Код операции | Операнды | Операция |
---|---|---|---|
ADDB3 |
81 |
add1, add2, sum |
sum ← add1 + add2 |
ADDW3 |
А1 |
||
ADDL3 |
С1 |
Например, инструкция на машинном языке
00000800 9F 00001000 9F 00001200 9F C1
вызовет сложение длинного слова, начинающегося с адреса ^X00001200, с длинным словом, начинающимся с адреса ^X00001000, а сумма будет помещена в длинное слово, расположенное по адресу ^X00000800. Если бы адресам ^X0000800, ^X00001000 и ^X00001200 соответствовали символические имена A, B и C, то эта инструкция могла быть написана на языке ассемблера следующим образом:
ADDL3 C,B,A
Семейство инструкций вычитания SUB подобно семейству инструкций сложения ADD. Ниже приведём шесть из них:
Мнемоника | Код операции | Операнды | Операция |
---|---|---|---|
SUBB2 |
82 |
sub, dif |
dif ← dif - sub |
SUBW2 |
А2 |
||
SUBL2 |
С2 |
||
SUBB3 |
83 |
sub, min, dif |
dif ← min - sub |
SUBW3 |
А3 |
||
SUBL3 |
С3 |
Семейство инструкций пересылки MOVB включает следующие инструкции:
Мнемоника | Код операции | Операнды | Операция |
---|---|---|---|
MOVB |
90 |
src, dst |
dst ← src |
MOVW |
B0 |
||
MOVL |
D0 |
||
MOVQ |
7D |
Инструкция MOVQ (MOVe Quadword) служит для пересылки 64-битового квадраслова.
Байт спецификатора операнда указывает способ определения местонахождения операнда. Рассмотренный ранее спецификатор операнда ^X9F указывает, что для нахождения операнда используется режим абсолютной адресации. Данный режим адресации указывает, что адрес операнда содержится в длинном слове, расположенном непосредственно после байта спецификатора операнда.
Режим непосредственной адресации подобен режиму абсолютной адресации, за тем исключением, что после байта спецификатора операнда непосредственно следует не адрес операнда, а сам операнд. Для указания режима непосредственной адресации используется спецификатор операнда ^X8F. Рассмотрим, например, следующую инструкцию на машинном языке:
Второй операнд | Первый операнд | Код операции |
---|---|---|
00000800 9F |
50 8F |
80 |
Код операции ^X80 соответствует инструкции ADDB2 - сложение байтов. Спецификатор первого операнда ^X8F указывает, что используется непосредственная адресация. В следующем байте содержится значение ^X50, которое является значением первого операнда. В остальных пяти байтах инструкции содержится указание, что для выборки второго операнда применяется абсолютная адресация, а сам операнд расположен по адресу ^X00000800. В результате по данной инструкции будет складываться значение ^X50 и содержимое байта памяти с адресом ^X00000800. Если перед выполнением данной инструкции значение этого содержимого равно ^X60, то после выполнения инструкции содержимое этого байта памяти будет равно значению ^XB0.
Подобным образом по следующей инструкции будет выполнено сложение числа ^X01234567 с содержимым длинного слова, начинающегося с адреса ^X00000A00:
Второй операнд | Первый операнд | Код операции |
---|---|---|
00000А00 9F |
01234567 8F |
С0 |
Поскольку коду операции ^XC0 или инструкции ADDL2 требуются операнды в формате длинного слова, то непосредственный операнд (в данном случае 01234567) размещается в четырёх байтах, следующих за байтом спецификатора операнда. Обратите внимание что ячейка памяти с адресом ^X01234567 никак не участвует в выполнении этой инструкции.
Операнды, содержащиеся в машинном коде самой инструкции, такие как 50 и 01234567 в предыдущих примерах, называются непосредственными операндами. Поскольку операнды находятся непосредственно в машинном коде самой инструкции, то они становятся доступными сразу же после выборки инструкции.
В языке ассемблера для указания непосредственной адресации используется знак номера #. Например, в следующих инструкциях на языке ассемблера:
ADDB2 #80,ALPHA ADDL2 #1000,BETA
знак номера #, стоящий перед первым операндом, укажет ассемблеру при трансляции этих инструкций на машинный язык, что используется непосредственная адресация.
Режим абсолютной адресации, определяемый спецификатором ^X9F, позволяет получать доступ к любой адресуемой области памяти. Однако такой режим является неэкономным с точки зрения распределения памяти. Например, программа в машинном коде, приведённая на рис. 3.5, повторно показана на рис. 3.6. Обратите внимание, что большинство байтов этой программы отводится для хранения адресов. Программа занимает 38 байтов памяти, из них 24 байта отведено для указания адресов.
Более эффективен другой способ адресации, называемый относительной адресацией. При относительной адресации местонахождение операнда задаётся разностью между действительным адресом нахождения операнда и текущим значением программного счётчика. Эта разность называется смещением. В сущности, смещение определяет местонахождение операнда по отношению к текущему адресу, т.е. предшествует ли адрес операнда текущему адресу или находится после него, а также насколько велико удаление адреса операнда относительно текущего. Вспомним, что программный счётчик PC содержит адрес текущей инструкции или части этой инструкции.
Чтобы понять, как работает относительная адресация, рассмотрим рис. 3.7. Программа, приведённая на рис. 3.7, идентична программе, показанной на рис. 3.6, за тем исключением, что вместо абсолютной адресации используется относительная. На рис. 3.7 вместо спецификатора операнда ^X9F применяется спецификатор ^XAF. Спецификатор ^XAF означает, что для указания адреса используется единственный байт. Если содержимое байта (рассматриваемое как число, представленное в дополнительном коде) является отрицательным, это означает, что операнд расположен в памяти перед текущим адресом и смещён относительно него на указанное число байтов. Если содержимое байта является положительным, это означает, что операнд размещается в памяти после текущего адреса через соответствующее число байтов.
Примечания | Содержимое | Адрес | ||
---|---|---|---|---|
БАЙТ ДАННЫХ |
|
|
1А |
00001000 |
БАЙТ ДАННЫХ |
|
|
26 |
00001001 |
БАЙТ ДАННЫХ |
|
|
05 |
00001002 |
РЕЗУЛЬТАТ (СУММА) |
|
|
?? |
00001003 |
MOVB ИНСТРУКЦИЯ |
0000100З 9F |
00001000 9F |
90 |
00001004 |
ADDB2 ИНСТРУКЦИЯ |
00001003 9F |
00001001 9F |
80 |
0000100F |
ADDB2 ИНСТРУКЦИЯ |
00001003 9F |
00001002 9F |
80 |
0000101А |
RET ИНСТРУКЦИЯ |
|
|
04 |
00001025 |
Рис. 3.6. Стандартный формат программы в машинном коде
Например, рассмотрим на рис. 3.7 инструкцию MOVB. Код операции ^X90 расположен по адресу ^X00001004. Содержимым байта с адресом ^X00001006 является код ^XAF, который указывает, что местонахождение первого операнда будет определяться с помощью относительной адресации. Следующий байт с адресом ^X00001006 содержит смещение ^XF9. Число ^XF9, интерпретируемое как число со знаком, эквивалентно десятичному числу - 7. После выборки из памяти смещения содержимое программного счётчика будет увеличено, так что он будет содержать адрес ^X00001007. Поэтому адресом первого операнда инструкции MOVB является
00001007 -7 00001000
Обратите внимание, что адрес операнда ^X00001000 совпадает с адресом первого операнда инструкции MOVB, представленной на рис. 3.6. Вычислить адрес остальных операндов предлагается читателю в качестве упражнения (См. п. 3 упр. 3.1).
Применение относительной адресации вместо абсолютной уменьшает объём памяти, занимаемый программой, с 38 до 20 байтов. Программа не только получается меньше, но и выполняется быстрее, так как при выполнении производится меньшее число выборок из памяти. Однако относительная адресация со смещением, заданным в формате байта, пригодна только для небольших программ, поскольку, задавая смещение в формате байта, максимально можно адресовать 127 ячеек после или 128 ячеек перед, относительно текущего значения программного счётчика. Чтобы избежать подобных ограничений, в ЭВМ семейства VAX для относительной адресации позволяется использовать слова и длинные слова. Эти режимы адресации распознаются по спецификаторам операндов ^XCF и ^XEF соответственно. Использование смещений, задаваемых в формате слова или длинного слова, не только увеличит объём программы, но и позволит также адресовать любое место в программе независимо от её объёма.
Режимы относительной адресации со смещением, заданным в формате байта, слова и длинного слова, можно найти в программах на языке ассемблера, приведённых в следующей главе, а более подробное описание этих режимов можно найти в гл. 7. Как мы увидим, кроме экономии времени выполнения и объёма занимаемой памяти относительная адресация имеет и другие преимущества. В результате когда ассемблер выполняет трансляцию операторов, таких как
MOVB A,B ADDL3 C,D,E
на машинный язык, то вместо абсолютной он использует относительную адресацию. Отметим, что применение последней не требует какой-либо дополнительной работы от программиста, так как смещение вычисляет сам ассемблер.
Примечания | Содержимое | Адрес |
---|---|---|
БАЙТ ДАННЫХ |
1А |
00001000 |
БАЙТ ДАННЫХ |
26 |
00001001 |
БАЙТ ДАННЫХ |
05 |
00001002 |
РЕЗУЛЬТАТ (СУММА) |
?? |
00001003 |
MOVB ИНСТРУКЦИЯ |
FA AF F9 AF 90 |
00001004 |
ADDB2 ИНСТРУКЦИЯ |
F5 AF F5 AF 80 |
0000100F |
ADDB2 ИНСТРУКЦИЯ |
F0 AF F1 AF 80 |
0000100F |
RET ИНСТРУКЦИЯ |
04 |
00001025 |
Рис. 3.7. Применение относительной адресации в программе на машин ном языке
Содержимое | Адрес |
---|---|
0000000F |
00000200 |
FFFFFFFF |
00000204 |
00000100 |
00000208 |
00000001 |
0000020C |
Опишите, что произойдёт при выполнении каждой из нижеследующих инструкций на машинном языке. Выпишите для каждой инструкции адрес и новое содержимое каждого длинного слова, если оно изменилось. (Считайте, что инструкции выполняются независимо друг от друга. Перед выполнением каждой инструкции байты памяти с адресами от ^X0200 до ^X020F принимают исходные значения, приведённые выше.)
а) | 00000208 9F |
00000200 9F |
D0 |
б) | 00000208 9F |
00000200 8F |
D0 |
в) | 00000204 9F |
0000020С 9F |
С0 |
г) | 00000204 9F |
0000020С 8F |
С0 |
д) | 0000020С 9F |
00000204 9F |
С2 |
е) | 00000204 9F |
00000010 8F |
00000208 9F С1 |
ж) | 00000204 9F |
00000208 9F |
00000020 8F С3 |
з) | 00000208 9F |
00000200 9F |
7D |
Инструкция | Адрес | |||
---|---|---|---|---|
|
00000200 9F |
00000020 8F |
D0 |
00000210 |
|
00000204 9F |
00000040 8F |
D0 |
0000021B |
00000208 9F |
00000200 9F |
00000204 9F |
C1 |
00000226 |
0000020С 9F |
00000208 9F |
0000000F 8F |
C3 |
00000236 |
|
|
|
04 |
00000246 |
Фортран | Паскаль |
---|---|
INTEGER J, K, L |
PROGRAM FOUR; |
J=15 |
VAR |
K=22 |
J, K, L: INTEGER; |
L=J-K+9 |
BEGIN |
STOP |
J := 15; |
END |
K := 22; |
|
L := J-K+9; |
|
END. |
|
.ENABLE |
ABSOLUTE |
J: |
.BLKL |
1 |
K: |
.BLKL |
1 |
DIF: |
.BLKL |
1 |
|
.ENTRY |
ADDRESS,0 |
FIRST: |
MOVL |
#512,J |
|
MOVL |
#64,K |
|
SUBL3 |
K,J,DIF |
LAST: |
$EXIT_S |
|
|
.END |
ADDRESS |
< НАЗАД | ОГЛАВЛЕНИЕ | ВПЕРЁД > |
[1] В действительности для повышения быстродействия в ЭВМ семейства VAX между процессором и памятью осуществляется одновременная передача двух или четырёх байтов в зависимости от модели ЭВМ. Однако наличие 16- и 32-битовых трактов передачи данных прозрачно для программиста, т. е. скрыто от него.
[2] В действительности некоторые коды операций действуют как управляющие коды, которые служат признаком того, что код определённой операции может быть найден в следующем байте. Это позволяет определять много дополнительных кодов операций. В настоящее время в ЭВМ семейства VAX реализовано всего около 300 кодов операций.