GNU MIX Development Kit (mdk): Учебник по MIX и MIXAL
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2. Учебник по MIX и MIXAL
В серии книг Искусство программирования Д. Кнута для иллюстрации алгоритмов и умений, необходимых каждому серьёзному программисту, автор использует виртуальный компьютер MIX (вместе с соответствующим набором двоичных инструкций). Как для любого реального компьютера, существует символический язык ассемблера, на котором можно программировать MIX -- язык ассемблера MIX, MIX assembly language, сокращённо MIXAL. В следующих подразделах вы найдёте учебник, который даст вам основы архитектуры MIX и научит программировать MIX на языке MIXAL.
компьютера MIX.
2.1 Компьютер MIX Архитектура и набор инструкций
2.2 MIXAL Язык ассемблера MIX.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1 Компьютер MIX
В этом разделе вы найдёте описание компьютера MIX, его компонентов и набора инструкций.
2.1.1 Архитектура MIX 2.1.2 Набор инструкций MIX
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.1 Архитектура MIX
Основной единицей информации в компьютере MIX является байт, в котором хранится положительное значение в диапазоне от 0 до 63. Имейте в виду, что байт MIX может быть представлен шестью битами, а не восемью, как регулярный байт. Если иное не оговорено специально, слово байт будет обозначать 6-битный байт MIX.
Слово MIX определяется как набор из пяти байтов и знака. Байты слова нумеруются от 1 до 5, первым является старший байт. Знак обозначается индексом 0. Графически,
----------------------------------------------- | 0 | 1 | 2 | 3 | 4 | 5 | ----------------------------------------------- | +/- | байт | байт | байт | байт | байт | ----------------------------------------------- |
Вы можете ссылаться на часть слова, используя спецификацию поля
(fspec) в виде: "(L:R)", где L обозначает
первый байт, а R -- последний байт поля. Когда L равно нулю,
поле включает знак слова. Спецификация может также быть представлена
одним числом F
, вычисляемым как F = 8*L + R
(так, спецификация
`(1:3)', обозначающая первые три байта слова, представляется числом 11).
Компьютер MIX сохраняет информацию в регистрах, хранящих либо слово, либо два байта и знак (см. ниже), и в ячейках памяти, каждая из которых содержит слово. Если быть точным, компьютер MIX имеет 4000 ячеек памяти с адресами от 0 до 3999 (т.е., для адресации ячейки памяти достаточно двух байтов) и следующие регистры:
rA
- Регистр A. Регистр общего назначения, хранящий слово. Обычно его содержимое служит операндом арифметических операций и инструкций сохранения в памяти.
rX
- Регистр X. Регистр общего назначения, хранящий слово. Часто выступает как расширение или замена `rA'.
rJ
- Регистр J (jump, переход). Этот регистр содержит положительное двухбайтовое значение, обычно представляющее адрес перехода.
rI1
,rI2
,rI3
,rI4
,rI5
,rI6
- Индексные регистры. Эти шесть регистров могут сохранять двухбайтовое значение со знаком. Их содержимое используется как индексирующее значение при вычислении эффективных адресов памяти.
Кроме того, компьютер MIX содержит:
- Триггер переполнения (один бит со значениями включен и выключен). В настоящем руководстве этот триггер обозначается OV.
- Индикатор сравнения (имеющий три значения: РАВНО, БОЛЬШЕ и МЕНЬШЕ). В настоящем руководстве этот индикатор обозначается CM, а его возможные значения сокращаются E (equal), G (greater) и L (less).
-
Блочные устройства ввода/вывода. Каждое устройство обозначено
un
, гдеn
пробегает значения от 0 до 20. В определении Кнута, устройства отu0
доu7
-- носители на магнитной ленте, отu8
доu15
-- диски и барабаны,u16
-- устройство чтения перфокарт,u17
-- устройство записи перфокарт,u18
-- строчный принтер,u19
-- текстовый терминал, иu20
-- перфоленточное устройство. Наша реализация отображает эти устройства в дисковые файлы, кромеu19
, представляющего собой стандартный вывод.
Как замечено выше, компьютер MIX взаимодействует с внешним миров с помощью набора устройств ввода/вывода, которые могут быть к нему "подключены". Компьютер обменивается информацией, используя блоки слов, длина которых зависит от устройства (see section 6.3 Блочные устройства MIX). Эти слова интерпретируются устройством либо как двоичная информация (для устройств 0-16), либо как представление печатаемых литер (устройства 17-20). В последнем случае каждый байт MIX отображается в литеру в соответствии со следующей таблицей:
00 | 01 | A | 02 | B | 03 | C | |
04 | D | 05 | E | 06 | F | 07 | G |
08 | H | 09 | I | 10 | d | 11 | J |
12 | K | 13 | L | 14 | M | 15 | N |
16 | O | 17 | P | 18 | Q | 19 | R |
20 | s | 21 | p | 22 | S | 23 | T |
24 | U | 25 | V | 26 | W | 27 | X |
28 | Y | 29 | Z | 30 | 0 | 31 | 1 |
32 | 2 | 33 | 3 | 34 | 4 | 35 | 5 |
36 | 6 | 37 | 7 | 38 | 8 | 39 | 9 |
40 | . | 41 | , | 42 | ( | 43 | ) |
44 | + | 45 | - | 46 | * | 47 | / |
48 | = | 49 | $ | 50 | < | 51 | > |
52 | @ | 53 | ; | 54 | : | 55 | ' |
Наконец, компьютер MIX имеет виртуальный центральный процессор, управляющий вышеперечисленными компонентами, который может выполнять богатый набор инструкций (составляющих его машинный язык, похожий на используемые в реальных центральных процессорах), включая арифметические и логические операции, инструкции помещения значения в память, сравнения и перехода. Являясь типичным компьютером фон Неймана, ЦП MIX последовательно (если только не встречается инструкция перехода) извлекает из памяти двоичные инструкции и сохраняет адрес следующей выполняемой инструкции во внутреннем регистре, называемом счётчиком положения (в других архитектурах также известен как программный счётчик).
Следующий раздел, See section 2.1.2 Набор инструкций MIX, даёт полное описание доступных двоичных инструкций MIX.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2 Набор инструкций MIX
В следующих подразделах полностью описан набор инструкций компьютера MIX. Мы начнём с описания структуры двоичной инструкции и используемой для ссылки на её поля нотации. Остальные подразделы посвящены описанию собственно инструкций, которые может использовать программист MIX.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2.1 Структура инструкции
Инструкции MIX кодируются словами со следующей структурой полей:
Поле | fspec | Описание |
ADDRESS | (0:2) | Первые два байта и знак являются полем адреса. Вместе с полем INDEX они обозначают используемый инструкцией адрес памяти. |
INDEX | (3:3) | Третий байт -- индекс, обычно используемый для модификации адреса(4). |
MOD | (4:4) | Четвёртый байт используется либо как модификатор кода операции, либо как спецификация поля. |
OPCODE | (5:5) | Последний (младший) байт слова определяет код операции. |
или, графически,
------------------------------------------------ | 0 | 1 | 2 | 3 | 4 | 5 | ------------------------------------------------ | ADDRESS | INDEX | MOD | OPCODE | ------------------------------------------------ |
Для каждой инструкции `M' обозначает адрес памяти, получаемый после модификации поля ADDRESS байтом INDEX, а `V' -- содержимое описываемого байтом MOD поля ячейки памяти с адресом `M'. Например, предположим, что содержимое регистров и ячеек памяти MIX таково:
[rI2] = + 00 63 [31] = - 10 11 00 11 22 |
ADDRESS = - 00 32 = -32 INDEX = 02 = 2 MOD = 11 = (1:3) OPCODE = 10 M = ADDRESS + [rI2] = -32 + 63 = 31 V = [M](MOD) = (- 10 11 00 11 22)(1:3) = + 00 00 10 11 00 |
Обратите внимание, при вычислении `V', используя слово и спецификацию поля, мы применяем к выбранным `MOD' байтам левое заполнение, чтобы получить в качестве результата целое слово.
В следующих подразделах мы присвои каждой инструкции MIX мнемонику или символическое имя. Например, мнемоникой инструкции с `OPCODE' 10 будет `LD2'. Таким образом, вышеприведённую инструкцию можно переписать:
LD2 -32,2(1:3) |
MNEMONIC ADDRESS,INDEX(MOD) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2.2 Команды загрузки
Для загрузки содержимого памяти в регистр могут использоваться следующие инструкции:
LDA
-
Поместить в rA содержимое ячейки памяти M.
OPCODE = 8, MOD = fspec.
rA <- V
. LDX
-
Поместить в rX содержимое ячейки памяти M.
OPCODE = 15, MOD = fspec.
rX <- V
. LDi
-
Поместить в rIi содержимое ячейки памяти M.
OPCODE = 8 + i, MOD = fspec.
rIi <- V
. LDAN
-
Поместить в rA содержимое ячейки памяти M с противоположным знаком.
OPCODE = 16, MOD = fspec.
rA <- -V
. LDXN
-
Поместить в rX содержимое ячейки памяти M с противоположным знаком.
OPCODE = 23, MOD = fspec.
rX <- -V
. LDiN
-
Поместить в rIi содержимое ячейки памяти M с противоположным знаком.
OPCODE = 16 + i, MOD = fspec.
rIi <- -V
.
Во всех вышеперечисленных инструкиях поле `MOD' выбирает байты из ячейки памяти с адресом `M', загружаемые в нужный регистр (указанный `OPCODE'). Например, слово `+ 00 13 01 27 11' представляет собой инструкцию:
LD3 13,1(3:3) ^ ^ ^ ^ | | | | | | | --- MOD = 27 = 3*8 + 3 | | --- INDEX = 1 | --- ADDRESS = 00 13 --- OPCODE = 11 |
[rI1] = - 00 01 [rI3] = + 24 12 [12] = - 01 02 03 04 05 |
V = [M](3:3) = (- 01 02 03 04 05)(3:3) = + 00 00 00 00 03 |
[rI1] = - 00 01 [rI3] = + 00 03 [12] = - 01 02 03 04 05 |
Чтобы ещё проиллюстрировать команды загрузки, приведём таблицу, показывающую содержимое `rX' после различных инструкций `LDX':
- `LDX 12(0:0) [rX] = - 00 00 00 00 00'
- `LDX 12(0:1) [rX] = - 00 00 00 00 01'
- `LDX 12(3:5) [rX] = + 00 00 03 04 05'
- `LDX 12(3:4) [rX] = + 00 00 00 03 04'
- `LDX 12(0:5) [rX] = - 01 02 03 04 05'
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2.3 Команды запоминания
Следующие инструкции обратны операциям загрузки -- они используются для запоминания поля регистра в памяти. Здесь MOD обозначает поле ячейки памяти, которое должно быть перезаписано байтами из регистра. Берутся самые правые байты регистра.
STA
-
Запомнить rA. OPCODE = 24, MOD = fspec.
V <- rA
. STX
-
Запомнить rX. OPCODE = 31, MOD = fspec.
V <- rX
. STi
-
Запомнить rIi. OPCODE = 24 + i, MOD = fspec.
V <- rIi
. STJ
-
Запомнить rJ. OPCODE = 32, MOD = fspec.
V <- rJ
. STZ
-
Запомнить ноль. OPCODE = 33, MOD = fspec.
V <- 0
.
Для примера, рассмотрим инструкцию `STA 1200(2:3)'. Она заставит MIX взять байты 4 и 5 регистра A и скопировать и в байты 2 и 3 ячейки памяти 1200 (помните, что в этих инструкциях MOD задаёт поле адреса памяти). Остальные байты ячейки памяти сохраняют своё значение. Так, если до выполнения инструкции:
[1200] = - 20 21 22 23 24 [rA] = + 01 02 03 04 05 |
[1200] = - 20 04 05 23 24 [rA] = + 01 02 03 04 05 |
Ещё один пример: `ST2 1000(0)' установит знак `[1000]' равным знаку `[rI2]'.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2.4 Арифметические команды
Следующие инструкции осуществляют арифметические операции над регистрами rA и rX и содержимым памяти.
ADD
-
Прибавить и установить OV при переполнении. OPCODE = 1, MOD = fspec.
rA <- rA +V
. SUB
-
Вычесть и установить OV при переполнении. OPCODE = 2, MOD = fspec.
rA <- rA - V
. MUL
-
Умножить V на rA и поместить 10-байтовое произведение в rAX.
OPCODE = 3, MOD = fspec.
rAX <- rA x V
. DIV
-
rAX рассматривается как 10-байтовое число и делится на V.
OPCODE = 4, MOD = fspec.
rA <- rAX / V
,rX
<- остаток.
Во всех вышеперечисленных инструкциях одним из операндов бинарной арифметической операции является `[rA]', другим -- `V' (заданное поле ячейки памяти с адресом `M'), заполненное нулевыми байтами слева до полного слова. В операциях умножения и деления регистр `X' играет роль правого расширения регистра `A', так что мы можем работать с 10-байтовыми числами, старшие байты которых располагаются в `rA' (знаком 10-байтового числа является знак `rA', знак `rX' игнорируется).
Сложение и вычитание слов MIX может приводить к переполнению, поскольку результат сохраняется в регистре, содержащем только 5 байтов (и знак). Если это происходит, в `rA' помещается результат операции по модулю 1 073 741 823 (максимальное значение, хранимое в слове MIX) и устанавливается триггер переполнения.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2.5 Команды пересылки адреса
В этих инструкциях `M' (адрес после модификации) используется как число, а не как адрес ячейки памяти. Соответственно, `M' может иметь любое допустимое для слова значение (т.е. не ограничено диапазонов адресов памяти 0-3999).
ENTA
-
Загрузить `M' в [rA]. OPCODE = 48, MOD = 2.
rA <- M
. ENTX
-
Загрузить `M' в [rX]. OPCODE = 55, MOD = 2.
rX <- M
. ENTi
-
Загрузить `M' в [rIi]. OPCODE = 48 + i, MOD = 2.
rIi <- M
. ENNA
-
Загрузить `-M' в [rA]. OPCODE = 48, MOD = 3.
rA <- -M
. ENNX
-
Загрузить `-M' в [rX]. OPCODE = 55, MOD = 3.
rX <- -M
. ENNi
-
Загрузить `-M' в [rIi]. OPCODE = 48 + i, MOD = 3.
rIi <- -M
. INCA
-
Увеличить [rA] на `M'. OPCODE = 48, MOD = 0.
rA <- rA + M
. INCX
-
Увеличить [rX] на `M'. OPCODE = 55, MOD = 0.
rX <- rX + M
. INCi
-
Увеличить [rIi] на `M'. OPCODE = 48 + i, MOD = 0.
rIi <- rIi + M
. DECA
-
Уменьшить [rA] на `M'. OPCODE = 48, MOD = 1.
rA <- rA - M
. DECX
-
Уменьшить [rX] на `M'. OPCODE = 55, MOD = 0.
rX <- rX - M
. DECi
-
Уменьшить [rIi] на `M'. OPCODE = 48 + i, MaOD = 0.
rIi <- rIi - M
.
В вышеперечисленных инструкциях поле `ADDRESS' (модифицированное) играет роль непосредственного операнда, и позволяет напрямую устанавливать содержимое регистров MIX без перенаправления к ячейкам памяти (в реальных процессорах это означает, что они выполняются быстрее, чем обсуждавшиеся ранее инструкции, операнды которых берутся из памяти). Так, если вы хотите поместить в `rA' значение -2000 (- 00 00 00 31 16), вы можете использовать двоичную инструкцию + 31 16 00 03 48, или, символически,
ENNA 2000 |
Имейте в виду, что в командах пересылки адреса поле `MOD' -- не спецификатор поля, а служит для определения (вместе с `OPCODE') конкретной выполняемой операции.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2.6 Команды сравнения
До сих пор мы изучали, как перемещать значения между регистрами и ячейками памяти MIX, а также как осуществлять арифметические операции над этими значениями. Но для написания нетривиальных программ нужны и другие возможности. Одна из наиболее общих -- возможность сравнивать два значения, которая, вместе с переходами, позволит обрабатывать условные операторы.
Следующие инструкции сравнивают значение регистра с `V' и соответствующим образом устанавливают индикатор CM (т.е., `E', `G' или `L', "равно", "больше" или "меньше" соответственно).
CMPA
- Сравнить [rA] с V. OPCODE = 56, MOD = fspec.
CMPX
- Сравнить [rX] с V. OPCODE = 63, MOD = fspec.
CMPi
- Сравнить [rIi] с V. OPCODE = 56 + i, MOD = fspec.
Как объяснено выше, эти инструкции изменяют значение индикатора сравнения MIX. Вы можете спросить, как можно использовать это значение. Для этого служат команды перехода, описанные в следующем подразделе.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2.7 Команды перехода
Компьютер MIX содержит внутренний регистр, называемый счётчиком
положения, сохраняющий адрес следующей инструкции, которая должна быть
получена из памяти и обработан виртуальным процессором. Вы не можете
напрямую изменять содержимое этого внутреннего регистра инструкцией
загрузки: после получения текущей инструкции он автоматически
увеличивается на 1 самим MIX. Тем не менее, существует набор инструкций
(называемых инструкциями перехода), которые могут изменять содержимое
счётчика положения при выполнении некоторого условия. При этом
значение адреса инструкции, которая выполнялась бы следующей, если бы
не было перехода, помещается в `rJ' (кроме JSJ
), а значение
счётчика положения устанавливается равным `M' (таким образом, следующая
инструкция берётся по этому новому адресу). Позднее вы можете вернуться
к отправной точке перехода, читая адрес, сохранённый в `rJ'.
Компьютер MIX имеет следующие инструкции перехода:
Эти инструкции выполняют обязательный переход по указанному адресу. Используйте `JSJ', если адрес возврата вам не нужен.
JMP
- Безусловный переход. OPCODE = 39, MOD = 0.
JSJ
- Безусловный переход без изменения rJ. OPCODE = 39, MOD = 1.
Эти инструкции для принятия решения о переходе проверяют триггер переполнения.
JOV
- Выполнить переход при установленном OV (OV сбрасывается). OPCODE = 39, MOD = 2.
JNOV
- Выполнить переход при сброшенном OV (OV остаётся сброшенным). OPCODE = 39, MOD = 3.
В следующих инструкциях переход обусловлен содержимым флага сравнения:
JL
-
Выполнить переход, если
[CM] = L
. OPCODE = 39, MOD = 4. JE
-
Выполнить переход, если
[CM] = E
. OPCODE = 39, MOD = 5. JG
-
Выполнить переход, если
[CM] = G
. OPCODE = 39, MOD = 6. JGE
-
Выполнить переход, если
[CM]
не равноL
. OPCODE = 39, MOD = 7. JNE
-
Выполнить переход, если
[CM]
не равноE
. OPCODE = 39, MOD = 8. JLE
-
Выполнить переход, если
[CM]
не равноG
. OPCODE = 39, MOD = 9.
Вы можете также осуществлять переход в зависимости от значений регистров MIX, используя следующие инструкции:
JAN
JAZ
JAP
JANN
JANZ
JANP
- Выполнить переход, если содержимое rA, соответственно, отрицательно, равно нулю, положитнльно, неотрицательно, не равно нулю или неположительно. OPCODE = 40, MOD = 0, 1, 2, 3, 4, 5.
JXN
JXZ
JXP
JXNN
JXNZ
JXNP
- Выполнить переход, если содержимое rX, соответственно, отрицательно, равно нулю, положительно, неотрицательно, не равно нулю или неположительно. OPCODE = 47, MOD = 0, 1, 2, 3, 4, 5.
JiN
JiZ
JiP
JiNN
JiNZ
JiNP
- Выполнить переход, если содержимое rIi, соответственно, отрицательно, равно нулю, положительно, неотрицательно, не равно нулю или неположительно. OPCODE = 40 + i, MOD = 0, 1, 2, 3, 4, 5.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2.8 Команды ввода/вывода
Как объясняется в предыдущих разделах (see section 2.1.1 Архитектура MIX), компьютер MIX может взаимодействовать с большим количеством блочных устройств. Для этого в вашем распоряжении имеются следующие инструкции:
IN
- Пересылает блок слов с указанного устройства в память, начиная с адреса M. OPCODE = 36, MOD = номер устройства.
OUT
- Пересылает блок слов из памяти (начиная с адреса M) на указанное устройство. OPCODE = 37, MOD = номер устройства.
IOC
- Выполняет управляющую команду (заданную M) к указанному устройству. OPCODE = 35, MOD = номер устройства.
JRED
- Выполнить переход по адресу M, если указанное устройство готово к работе. OPCODE = 38, MOD = номер устройства.
JBUS
- Выполнить переход по адресу M, если заданное устройство занято. OPCODE = 34, MOD = номер устройства.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2.9 Команды преобразования
Следующие инструкции осуществляют преобразования между числовыми значениями и их литерными представлениями.
NUM
- Преобразует rAX, содержимое которого рассматривается как литерное представляение числа, в его числовое значение и помещает его в rA. OPCODE = 5, MOD = 0.
CHAR
- Преобразует число, помещённое в rA, в литерное представление и помещает его в rAX. OPCODE = 5, MOD = 1.
[rA] = + 30 30 31 32 33 [rX] = + 31 35 39 30 34 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2.10 Команды сдвига
Следующие инструкции осуществляют побайтовый сдвиг содержимого `rA' и `rX'.
SLA
SRA
SLAX
SRAX
SLC
SRC
- Сдвинуть rA или rAX налево или направо или сдвинуть rAX циклически (см. пример ниже) налево или направо. M задаёт число байтов, на которое проивзодится сдвиг. OPCODE = 6, MOD = 0, 1, 2, 3, 4, 5.
SLA 2 | [rA] = - 03 04 05 00 00 |
SRA 1 | [rA] = - 00 01 02 03 04 |
SLC 3 | [rA] = - 04 05 01 02 03 |
SRC 24 | [rA] = - 05 01 02 03 04 |
[rA] = + 04 05 06 07 08 [rX] = - 09 10 00 00 00 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2.11 Прочие команды
Наконец, приведём список трёх остальных инструкций MIX, не описанных в предыдущих подразделах:
MOVE
- Переместить MOD слов с адреса M по адресу, хранящемуся в rI1. OPCODE = 7, MOD = число слов.
NOP
- Нет операции. OPCODE = 0, MOD = 0.
HLT
- Останов. Прекратить разбор инструкций. OPCODE = 5, MOD = 2.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.1.2.12 Временные характеристики
При написании программ на MIXAL (или любых других программ) нас часто интересует время их выполнения. Приблизительно, нас интересует ответ на вопрос: как долго будет выполняться программа? Конечно, это время выполнения является функцией от объёма входных данных, и ответ на наш вопрос обычно даётся в виде асимптотического поведения функции от объёма входных данных. В любом случае, для вычисления асимпотического приближения нам нужна мера времени выполнения одной инструкции на нашем (виртуальном) процессоре. Поэтому с каждой инструкцией MIX связано время выполнения, заданное в относительных единицах (в реальных компьютерах значение этой единицы зависит от аппаратной конфигурации). Когда наша виртуальная машина MIX выполняет программы, она может (по желанию) выводить значение времени выполнения на основе времени выполнения каждой отдельной инструкции.
В следующей таблице приведены значения времени выполнения (в вышеупомянутых относительных единицах) инструкций MIX.
NOP | 1 | ADD | 2 | SUB |
2 | MUL | 10 |
DIV | 12 | NUM | 10 | CHAR |
10 | HLT | 10 |
SLx | 2 | SRx | 2 | LDx |
2 | STx | 2 |
JBUS | 1 | IOC | 1 | IN |
1 | OUT | 1 |
JRED | 1 | Jx | 1 | INCx |
1 | DECx | 1 |
ENTx | 1 | ENNx | 1 | CMPx |
1 | MOVE | 1+2F |
В таблице 'F' обозначает число перемещаемых блоков (заданное полем
FSPEC
инструкции), SLx
и SRx -- сокращения для операций
побайтового сдвига, LDx
обозначает все операции загрузки,
STx
-- все операции запоминания, Jx
обозначает
все операции перехода, и т.д. для остальный сокращений.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.2 MIXAL
В предыдущих разделах мы перечислили все существующие двоичные инструкции MIX. Как мы показали, каждая инструкция представляется словом, которое достаётся из памяти и обрабатывается виртуальным центральным процессором MIX. Как и в случае реальных компьютеров, MIX может декодировать инструкции в двоичном формате (так называемый машинный язык), но программист-человек, пишущий программу на машинном языке, вряд ли весело проведёт время. К счастью, MIX можно программировать на языке ассемблера, MIXAL, предоставляющем способ написания понимаемых воображаемым компьютером MIX двоичных инструкций в символьном виде. Если вы ранее использовали языки ассемблера, вы найдёте в MIXAL очень много знакомого. Исходные файлы MIXAL транслируются в машинный язык ассемблером MIX, создающим двоичный файл (реальная программа MIX), который может быть непосредственно загружен в память MIX и последовательно выполнен.
В этом разделе мы опишем MIXAL, язык ассемблера MIX. Реализации ассемблера MIX и эмулятора компьютера MIX, входящие в состав MDK, описаны позднее (see section 3. Начало работы).
2.2.1 Базовая структура программы Написание базовых программ на MIXAL. 2.2.2 Директивы MIXAL Директивы ассемблера. 2.2.3 Выражения 2.2.4 W-выражения Вычисление w-выражений. 2.2.5 Локальные символы 2.2.6 Литеральные константы
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.2.1 Базовая структура программы
Ассемблер MIX читает файлы MIXAL построчно, создавая, при необходимости, двоичную инструкцию, связанную с определённым адресом в памяти. Чтобы следить за текущим адресом, ассемблер поддерживает внутренний счётчик положения, увеличиваемый при каждой компиляции инструкции. Кроме инструкция MIX в файл MIXAL можно включать директивы ассемблера (или псевдоинструкции), предназначенные для самого ассемблера (например, указывающие, где начинается и заканчивается программа, или переопределяющие счётчик положения, см. ниже).
Инструкции MIX и директивы ассемблера(7) записываются на MIXAL (одна на строку исходного файла) в соответствии со следующим шаблоном:
[LABEL] MNEMONIC [OPERAND] [COMMENT] |
где `ОПЕРАНД' имеет вид:
[ADDRESS][,INDEX][(MOD)] |
Элементы, заключённые в круглые скобки могут отсутствовать.
LABEL
- -- алфавитно-цифровой идентификатор (символ), получающий текущее значений счётчика положения, и может быть использован в последующих выражениях,
MNEMONIC
- -- литерал, обозначающий код операции инструкции (например,
LDA
,STA
, see section 2.1.2 Набор инструкций MIX) или псевдоинструкцию ассемблера (например,ORIG
,EQU
), ADDRESS
- -- выражение, описывающее поле адреса инструкции,
INDEX
- -- выражение, описывающее поле индекса инструкции, по умолчанию 0 (т.е.
индекс не используется). Может использоваться только если присутствует
ADDRESS
, MOD
- -- выражение, описывающее поле модификатора инструкции. Значение по
умолчанию, если выражение опущено, зависит от
OPCODE
, COMMENT
- любое количество пробелов после операнда обозначает начало комментария, т.е. любой текст, отделённый пробелами от операнда ассемблером игнорируется (имейте в виду, что пробелы внутри поля `OPERAND' недопустимы).
Обратите внимание, что между полями ADDRESS
, INDEX
и
MOD
, если они присутствуют, пробелы недопустимы.
Для разделения метки, кода операции и операнда в инструкции используются
пробелы(8).
Мы уже перечислили мнемоники, сопоставленные каждой инструкции MIX. Приведём пример инструкций MIXAL, представляющих инструкции MIX:
HERE LDA 2000 HERE представляет текущий счётчик положения LDX HERE,2(1:3) это комментарий JMP 1234 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.2.2 Директивы MIXAL
Инструкция MIXAL может быть либо одной из машинных инструкций MIX (see section 2.1.2 Набор инструкций MIX), либо одной из следующих псевдоинструкций ассемблера:
ORIG
- Устанавливает значение адреса памяти, по которому будет расположена после компиляции следующая инструкция.
EQU
-
Используется для определения значения символа, например,
SYM EQU 2*200/3
. CON
- Значение заданного выражения непосредственно копируется в память по текущему адресу.
ALF
- Принимает в качестве операнда пять литер, составляющих пять байтов слова, которое непосредственно копирует в память по текущему адресу.
END
- Обозначает конец программы. Операнд этой инструкции содержит адрес, с которого начинается выполнение программы.
Операндом ORIG
, EQU
, CON
и END
может
быть любое выражение, задающее слово MIX-константу, т.е. либо простое
выражение MIXAL (состоящее из чисел, символов и бинарных операций,
see section 2.2.3 Выражения), либо w-выражение (see section 2.2.4 W-выражения).
Любая программа на MIXAL должна содержать директиву END
с двоякой
целью: во-первых, она обозначает точку прекращения работы ассемблера,
и во-вторых, её (обязательный) операнд указывает начальный адрес
скомпилированной программы (адрес, по которому виртуальная машина MIX
должна начать разбор инструкций после загрузки программы). Также
является обычной практикой (хотя и не обязательно) включать в программу
по крайней мере одну директиву ORIG
, чтобы обозначить начальное
значение счётчика положения ассемблера (помните, что он содержит адрес,
связанные с каждой скомпилированной инструкцией MIX). Таким образом,
минимальной программой на MIXAL будет:
ORIG 2000 установить начальный адрес компиляции NOP эта инструкция будет загружена по адресу 2000 HLT а эта по адресу 2001 END 2000 конец программы, начало по адресу 2000 эта строка не анализируется ассемблером |
NOP
(+ 00 00 00 00 00)
и HLT
(+ 00 00 02 05)), которые будут загружены по адресам
2000 и 2001. Выполнение программы начнётся с адреса 2000. Каждая
программа на MIXAL должна также содержать инструкцию HLT
,
которая означает конец выполнения программы (но не компиляции программы).
Директива EQU
позволяет определять символические имена заданных
значений. Например, мы можем переписать вышеприведённую программу
следующим образом:
START EQU 2000 ORIG START NOP HLT END START |
LABEL
инструкции MIXAL. В этом случае перед компиляцией
строки ассемблер присвоит символу значение счётчика положения. Поэтому
третий способ записи нашей тривиальной программы:
ORIG 2000 START NOP HLT END START |
Директива CON
позволяет непосредственно задавать содержимое,
находящееся в памяти по адресу, указанному счётчиком положения. Например,
если ассемблер встретит следующий участок кода:
ORIG 1150 CON -1823473 |
Наконец, директива ALF
позволяет задавать содержимое памяти
как набор пяти литер (в кавычках), которые транслируются ассемблером
в соответствующие значения байтов, создавая, таким образом, двоичное
слово, размещаемое в соответствующей ячейке памяти. Эта директива
полезна, если вам нужно поместить по адресу памяти сообщения для печати,
как в следующем примере:
OUT MSG MSG здесь ещё не определено (ссылка вперёд) MSG ALF "THIS " MSG определяется здесь ALF "IS A " ALF "MESSA" ALF "GE. " |
MSG
) до его
реального определения. Ассемблер MIXAL может обрабатывать ссылки вперёд
с некоторыми ограничениями, описанными в следующем разделе
(see section 2.2.3 Выражения).
Любая строка, начинающаяся со звёздочки, считается комментарием и игнорируется ассемблером.
* Это комментарий: эта строка игнорируется. * Это ошибка: * должна быть в первой колонке. |
Как показано в предыдущем разделе, комментарии могут также быть расположены
после поля OPERAND
инструкции, отделённые от него пробелами:
LABEL LDA 100 Это также комментарий |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.2.3 Выражения
ПоляADDRESS
, INDEX
и MOD
инструкции MIXAL могут
быть выражениями, состоящими из чисел, идентификаторов и знаков бинарных
операций (+ - * / // :
). +
и -
могут также использоваться
как знаки унарных операций. Операторы выполняются слева направо, других
правил приоритета операторов нет, и использовать скобки для группировки
нельзя. Отдельная звёздочка обозначает текущее положение в памяти. Так,
например:
4+2** |
обозначает 6 (4+2), умноженное на текущее положение в памяти. Пробелы внути выражений не допускаются.
Специальная бинарная операция :
имеет то же значения, что и в
спецификациях полей, т.е.
A:B = 8*A + B |
A//B
обозначает деление 10-байтового числа
A
00 00 00 00 00 (A, дополненное справа пятью нулевыми байтами,
или, что то же самое, умноженное на 64 в пятой степени), разделённое
на B
. Примеры выражений:
18-8*3 = 30 14/3 = 4 1+3:11 = 4:11 = 43 1//64 = (01 00 00 00 00 00)/(00 00 00 01 00) = (01 00 00 00 00) |
Все символы, встречающиеся в выражениях, должны бы предварительно определены.
Ссылки вперёд допускаются только если встречаются отдельно (или с унарной
операцией) в части ADDRESS
инструкции MIXAL, например:
* OK: отдельная ссылка вперёд STA -S1(1:5) * ERROR: ссылка вперёд в выражении LDX 2-S1 S1 LD1 2000 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.2.4 W-выражения
Помимо описанных выше (see section 2.2.3 Выражения) выражений, ассемблер MIXAL
может обрабатывать в качестве операндов директив ORIG
, EQU
,
CON
и END
(see section 2.2.2 Директивы MIXAL) так называемые
w-выражения. Общий вид w-выражения таков:
WEXP = EXP[(EXP)][,WEXP] |
EXP
обозначает выражение, а квадратные скобки отмечают
необязательные элементы. Таким образом, w-выражение состоит из выражения,
за которым следует необязательное выражение в круглых скобках, а затем
любое число аналогичных конструкций, разделённых запятыми. Примеры
w-выражений:
2000 235(3) S1+3(S2),3000 S1,S2(3:5),23 |
W-выражения вычисляются слева направо следующим образом:
- Вначале общему результату `w' присвоить значение 0.
- Взять первое выражение разделённого запятыми списка и вычислить его. Например, при вычислении w-выражения `S1+2(2:4),2000(S2)', в первую очередь вычисляется `S1+2'. Пусть `S1' равно 265230, тогда `S1+2 = 265232 = + 00 01 00 48 16'.
- Вычислить выражение в круглых скобках, сводя его к спецификации поля вида `L:R'. В нашем предыдущем примере выражение в круглых скобках уже имеет нужный вид: 2:4.
- Подставить вместо байтов общего результата `w', обозначенных спецификацией поля, байты из значения предыдущего выражения. В нашем примере `w = + 00 00 00 00 00', и мы должны подставить вместо второго, третьего и четвёртого байтов байты из 265232. Мы берём три младших байта: 00 48 и 16 и ставим их во вторую, третью и четвёртую позиции `w', получая `w = + 00 00 48 16 00'.
- Повторить эту операцию для остальных выражений, работая в новым значением `w'. В нашем примере, если, скажем `S2 = 1:1', мы должны подставить вместо первого байта `w' младший байт 2000, т.е. 16 (поскольку 2000 = + 00 00 00 31 16), и поэтому мы получим `265232(1:4),2000(1:1) = + 16 00 48 16 00 = 268633088'.
Ещё один пример -- в w-выражении
1(1:2),66(4:5) |
1(1:1),2(2:2),3(3:3),4(4:4) = 01 02 03 04 00 |
Как указано выше, w-выражения могут встречаться только в операндах
директив MIXAL, принимающих константное значений (ORIG
, EQU
,
CON
и END
). Ссылки вперёд в w-выражениях не
допускаются (т.е., все символы, встречающиеся в w-выражении должны
быть определены до их использования).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.2.5 Локальные символы
Помимо определённых пользователем символов, программисты на MIXAL
могут использовать так называемые локальные символы, т.е.
символы вида [1-9][HBF]
. Локальный символ nB
ссылается
на адрес, где в последний раз в качестве метки служило nH
,
а nF
-- на следующее появление nH
. В отличие от
определённых пользователем символов, nH
может встречаться
в части LABEL
различных инструкций MIXAL сколько угодно раз.
Следующий код даёт пример использования локальных символов:
* строка 1 1H LDA 100 * строка 2: 1B ссылается на адрес строки 1, 3F ссылается на адрес строки 4 STA 3F,2(1B//2) * строка 3: переопределение 1H 1H STZ * строка 4: 1B ссылается на адрес строки 3 3H JMP 1B |
Имейте в виду, что локальный символ B
никогда не ссылается на
определение его собственной строки. Так, в следующей программе:
ORIG 1999 ST NOP 3H EQU 69 3H ENTA 3B локальный символ 3B ссылается на 3H в предыдущей строке HLT END ST |
ORIG
существует
особый трюк. Рассмотрим(9):
ORIG 1999 ST NOP 3H CON 10 ENT1 * LDA 3B ** rI1 = 2001, rA = 10. До сих пор всё нормально! 3H ORIG 3B+1000 ** в этой точке 3H равно 2003 ** а счётчик положений равен 3000. ENT2 * LDX 3B ** rI2 содержит 3000, rX содержит 2003. HLT END ST |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
2.2.6 Литеральные константы
MIXAL допускает введение литеральных констант, которые автоматически
помещаются ассемблером в память по адресам после конца программы.
Литеральные константы обозначаются =wexp=
, где wexp
--
w-выражение (see section 2.2.4 W-выражения). Например, код:
L EQU 5 LDA =20-L= |
вынуждает ассемблер добавить после конца программы инструкцию,
содержащую 15 (`20-L') и ассемблировать вышеприведённый код
как инструкцию LDA a
, где a
обозначает адрес,
по которому помещается значение 15. Другими словами, скомпилированный
код эквивалентен следующему:
L EQU 5 LDA a ... a CON 20-L END start |
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on June, 9 2003 using texi2html