MIX
MIX — це гіпотетичний комп'ютер, використаний в монографії Дональда Кнута, «Мистецтво програмування». Номер моделі комп'ютера MIX — 1009, походить від комбінації номерів і назв комерційних моделей машин, сучасних часу написання книги які здалися автору значущими. Крім того, «MIX» дорівнює 1009 в Римській системі числення.
MIX 1960-х був замінений новою (також гіпотетичною) комп'ютерною архітектурою, MMIX, яка буде включена в очікуваній редакції TAOCP. Програмні реалізації MIX і MMIX архітектур були розроблені різними авторами і вільно доступні (наприклад, розроблені самим Кнутом MIXware і MMIXware).
Існують деякі MIX/MMIX емулятори, які забезпечують роботу програмного забезпечення для комп'ютерів MIX на інших архітектурах. Одним із таких пакетів програмного забезпечення є GNU MDK; він є вільним і працює на різних платформах.
Архітектура
MIX являє собою гібридний двійково-десятковий комп'ютер. Коли комп'ютер програмується в бінарному режимі, кожен байт має 6 біт (значення від 0 до 63). У десятковому режимі кожен байт має 2 десяткових знаки (значення від 0 до 99). Байти згруповані в слова по п'ять байт зі знаком. Більшість програм, написаних для MIX, будуть працювати як в бінарному, так і в десятковому режимах, поки вони не спробують зберегти значення більше 63 в одному байті.
Слово змінюється в межах від −1.073.741.823 до 1.073.741.823 (включно) в бінарному режимі і від −9.999.999.999 до 9.999.999.999 (включно) в десятковому режимі. У комп'ютері MIX розрізняються числа −0 і +0, чого немає на сучасних комп'ютерах, в яких є тільки одне подання нуля, але кількість негативних чисел, які можуть бути представлені певною кількістю біт, на одиницю більше кількості позитивних чисел.
Регістри
У комп'ютері MIX 9 регістрів:
- rA: Акумуляторний регістр (accumulator) (повне слово (full word), п'ять байт зі знаком);
- rX: Розширення (extension) (повне слово, п'ять байт зі знаком);
- rI1, rI2, rI3, rI4, rI5, rI6: Індексні регістри (Два байти і знак);
- rJ: Адреса переходу (два байти, завжди позитивний).
Вважається, що байт має, як мінімум, 6 біт. Більшість інструкцій можуть вказувати, які з полів (байт) регістра потрібно змінити, використовуючи суфікс у формі (перший: останній). Нульове поле — однобітових знак.
MIX також записує, чи викликала попередня операція переповнення і один з трьох індикаторів (менше, дорівнює або більше). На діаграмі нижче кожен регістр показаний розділеним на свої поля.
|
|
|
|
|
|
|
|
|
|
|
Пам'ять і введення/виведення
Комп'ютер MIX має 4000 слів зберігання (кожен по 5 байт зі знаком), що адресуються з 0 до 3999. Крім того, є безліч пристроїв введення та виведення:
- Магнітофонні пристрої (пристрої 0 ... 7);
- Диск або барабанні пристрої (пристрої 8 ... 15);
- Пристрій читання карт (пристрій 16);
- Картковий перфоратор (пристрій 17);
- Порядковий принтер (пристрій 18);
- Друкарська машинка (пристрій 19);
- Перфострічка (пристрій 20).
Інструкції
Кожна машинна інструкція в пам'яті займає одне слово і складається з 4 частин: адреса (2 байта зі знаком) в пам'яті для читання або запису, вказівка індексного регістра (1 байт, що визначає, який індексний регістр rI використовувати) для додавання до адреси, модифікація ( 1 байт), що визначає, які частини регістру або комірки пам'яті будуть прочитані або змінені, і код операції (1 байт). Всі коди операції мають словесні позначення.
Програми MIX часто використовують код який самомодифікується, зокрема, щоб повернутися з підпрограми, так як в MIX відсутній автоматичний стек підпрограм.
Програми для комп'ютера MIX звичайно пишуться на MIXAL асемблері.
Команди завантаження
Вміст поля за адресою [ADDR + rIi (вміст регістра I з індексом i)] завантажується в регістр.
LDA ADDR, i(0 : 5) | rA := memory[ ADDR + rIi ]; | завантажити в A |
---|---|---|
LDX ADDR, i(0 : 5) | rX := memory[ ADDR + rIi ]; | завантажити в X |
LDi ADDR, i(0 : 5) | rIi := memory[ ADDR + rIi ]; | завантажити в I з індексом i |
LDAN ADDR, i(0 : 5) | rA := -memory[ ADDR + rIi ]; | завантажити в A з протилежним знаком |
LDXN ADDR, i(0 : 5) | rX := -memory[ ADDR + rIi ]; | завантажити в X з протилежним знаком |
LDiN ADDR, i(0 : 5) | rIi := -memory[ ADDR + rIi ]; | завантажити в Ii з протилежним знаком |
Команди запису в пам'ять
Записує вміст регістра в елемент пам'яті з адресою [ADDR + rIi]
STA ADDR, i(0 : 5) | memory[ ADDR + rIi ] := rA; | записати A |
---|---|---|
STX ADDR, i(0 : 5) | memory[ ADDR + rIi ] := rX; | записати X |
STi ADDR, i(0 : 5) | memory[ ADDR + rIi ] := rIi; | записати Ii |
STJ ADDR, i(0 : 5) | memory[ ADDR + rIi ] := rJ; | записати J |
STZ ADDR, i(0 : 5) | memory[ ADDR + rIi ] := 0; | обнулити вміст клітинки |
Арифметичні команди
ADD ADDR, i(0 : 5) | rA := rA + memory[ ADDR + rIi ]; | додавання |
---|---|---|
SUB ADDR, i(0 : 5) | rA := rA - memory[ ADDR + rIi ]; | віднімання |
MUL ADDR, i(0 : 5) | (rA, rX) := rA * memory[ ADDR + rIi ]; | множення |
DIV ADDR, i(0 : 5) | rA := int((rA, rX) / memory[ ADDR + rIi ]); rX := (rA, rX) % memory[ ADDR + rIi ]; |
ділення |
Команди операцій з адресами
ENTA ADDR, i | rA := ADDR + rIi; |
---|---|
ENTX ADDR, i | rX := ADDR + rIi; |
ENT? ADDR, i | rI? := ADDR + rIi; |
ENNA ADDR, i | rA := - ADDR - rIi; |
ENNX ADDR, i | rX := - ADDR - rIi; |
ENN? ADDR, i | rI? := - ADDR - rIi; |
INCA ADDR, i | rA := rA + ADDR + rIi; |
INCX ADDR, i | rX := rX + ADDR + rIi; |
INC? ADDR, i | rI? := ADDR + rIi; |
DECA ADDR, i | rA := rA - ADDR - rIi; |
DECX ADDR, i | rX := rX - ADDR - rIi; |
DEC? ADDR, i | rI? := rI? - ADDR - rIi; |
Команди порівняння
CMPA ADDR, i(0 : 5) | compare rA with memory[ ADDR + rIi ]; |
---|---|
CMPX ADDR, i(0 : 5) | compare rX with memory[ ADDR + rIi ]; |
CMP? ADDR, i(0 : 5) | compare rI? with memory[ ADDR + rIi ]; |
Команди переходу
JMP ADDR, i | goto ADDR + rIi; |
---|---|
JSJ ADDR, i | goto ADDR + rIi; rJ не міняється! |
JOV ADDR, i | if (overflow) then overflow := false; goto ADDR + rIi; |
JNOV ADDR, i | if (no overflow) then goto ADDR + rIi; else overflow := false; |
JL, JE, JG ADDR, i JGE, JNE, JLE ADDR, i |
if (less, equal, greater) then goto ADDR + rIi; if (no less, unequal, no greater) then goto ADDR + rIi; |
JAN/JAZ/JAP ADDR, i JANN/JANZ/JANP ADDR, i |
if (rA < 0 or rA == 0 or rA > 0) then goto ADDR + rIi; if (rA >= 0 or rA != 0 or rA <= 0) then goto ADDR + rIi; |
JXN/JXZ/JXP ADDR, i JXNN/JXNZ/JXNP ADDR, i |
if (rX < 0 or rX == 0 or rX > 0) then goto ADDR + rIi; if (rX >= 0 or rX != 0 or rX <= 0) then goto ADDR + rIi; |
J?N/J?Z/J?P ADDR, i J?NN/J?NZ/J?NP ADDR, i |
if (rI? < 0 or rI? == 0 or rI? > 0) then goto ADDR + rIi; if (rI? >= 0 or rI? != 0 or rI? <= 0) then goto ADDR + rIi; |
Інші команди
MOVE ADDR, i(F) | for(n = 0; n < F; n++, rI1++) memory[ ADDR + rIi + n ] := memory[ rI1 ]; |
---|---|
SLA/SRA ADDR, i SLAX/SRAX ADDR, i SLC/SRC ADDR, i |
shift rA to the left/right by ADDR+rIi bytes shift (rA, rX) to the left/right by ADDR+rIi bytes rotate (rA, rX) to the left/right by ADDR+rIi bytes |
NOP | do nothing; |
HLT | halt execution; |
Команди введення-виведення
IN ADDR, i( F ) | read in one block from input unit F into memory[ ADDR + rIi ] onwards; |
---|---|
OUT ADDR, i( F ) | output one block to unit F from memory[ ADDR + rIi ] onwards; |
IOC ADDR, i( F ) | send control instruction to i/o unit F; |
JRED ADDR, i( F ) | if (i/o unit F is ready) then goto ADDR + rIi; |
JBUS ADDR, i( F ) | if (i/o unit F is busy) then goto ADDR + rIi; |
команди перетворення
NUM | rA := numerical value of characters in ( rA,rX ); |
---|---|
CHAR | ( rA, rX ) := character codes representing value of rA; |
Посилання
- MMIX 2009: A RISC Computer for the Third Millennium Knuth’s official MIX page
- MMIX News Knuth’s official MIX news
- MMIXware: A RISC Computer for the Third Millennium Knuth’s official MIX book
- Open Directory: Computers: Programming: Languages: Assembly: MIX-MMIX many MIX-MMIX/MIXAL-MMIXAL links