|
Первый
компьютер - "Электроника-60"
На
этой страничке мне хотелось бы
коротко рассказать об очень широко
распространенной в свое время ЭВМ
"Электроника-60" - имеются в виду
ВУМС, ДВК и прочие на ее базе. По
нынешним временам, конечно,
возможности этой "персоналки"
смешны, но тем не менее многое в ней
заслуживает внимания. Тем более что
это машина, на которой я учился
программировать :-)
Сразу
отмечу, что данная статья ни в коей
мере не претендует на полное и
абсолютно точное техническое
описание, да и вряд ли такое кому-то
нужно. Ну а если все-таки нужно -
отсылаю к великолепной по содержанию
и ужасной по оформлению полу-книге,
полу-брошюре "Центральный
процессор М2". Читалась она (для
начинающего) очень тяжело, но в ней
было ВСЕ. Абсолютно ВСЕ. Даже пример
схемы внешнего устройства.
Итак,
сперва смешное. Вот некоторые
выдержки из описания центрального
процессора М2, на основе которого и
были построены вышеуказанные ЭВМ.
| Разрядность слова, бит |
16 |
А
это - реальная распечатка моей
программы, которая мерила (или по
крайней мере пыталась мерить)
быстродействие процессора для
различных методов адресации.
Насколько я помню, это относилось
к ДВК-2 |
| Объем логического
адресного пространства, К слов |
32 |
Емкость резидентного ОЗУ,
К слов |
4 |
| Число команд |
81 |
| Быстродействие, оп/сек |
250 000 |
Разрядность чисел с
плавающей запятой |
32 |
Число БИС (больших
интегральных схем) |
5 |
| Размеры платы, мм |
240 х 280 |
Построенный
на базе "Электроники-60"
вычислительный комплекс ВУМС имел
примерно такой вид:
|
|

|
Питание-
от 3-фазной сети 380В
Потребляемая
мощность
- не более 1750 Вт
Впрочем,
габариты его могли быть и
значительно уменьшены - системный
блок (3) и ГМД-70(2) поднимались выше,
дисплей (4) ставился в стойку, да и
принтер мог быть поменьше...
|
|
Ну
а теперь коротко о архитектуре -
преимущественно с точки зрения
программиста.
Системный
блок, на картинке - это (3) представлял
собой корзину, в которую вставлялись
платы - процессора и периферии. Плата
процессора всегда ставилась сверху,
потому что система прерываний в "Электронике-60"
отличалась от более привычной нам
теперь IBM-овской. Если совсем
примитивно - то линии запроса
прерывания (к процессору) и
предоставления прерывания (от
процессора) проходили по корзине,
скажем так, сверху вниз -
соответственно, наивысший приоритет
имела ближайшая к процессору плата. А
вектор прерывания процессору
сообщала сама плата периферии, так
что ситуации нехватки линий IRQ там
быть не могло - векторов было 256. Да,
еще - при обращении процессора к
какому-либо адресу - или ОЗУ, или
внешнего устройства - аппаратура
должна была сформировать сигнал "СИП"
(СИнхронизация Пассивного) -
отсутствие которого вызывало
прерывание "обращение к
несуществующей ячейке памяти". В
IBM-овской архитектуре процессор
просто ничего не заметит.
На
системном блоке (справа) были три
тумблера - питания, перевода в
шаговый режим и включения таймера.
Перевод в шаговый режим - по сути это
была зашитая в ПЗУ программа
монитора, если ее можно так назвать. С
ее помощью можно было просматривать
и изменять содержимое памяти и
регистров, проходить программу по
шагам, запускать тесты, загружаться и
так далее.
Для
программиста "Электроника-60"
представляла собой восемь 16-ти
разрядных регистров R0-R7, слово
состояния процессора, ОЗУ и регистры
внешних устройств, которые
находились в верхних 4 кБ адресного
пространства.
Регистры
R0-R5 были регистрами общего
назначения (РОН), R6 - указатель стека SP,
R7 - счетчик команд PC. Но в отличие от
привычных нам AX,BX... все регистры были
абсолютно равнозначны, то есть можно
было написать ADD #10, PC и получить JMP.
Хотя делать такого не
рекомендовалось. Кстати, в
двухоперандных командах и приемник и
источник могли быть в памяти - в
произошедших от 8086 процессорах
такого нет до сих пор, если не считать
достаточно своеобразные "строковые"
команды.
К
ячейкам памяти можно было
адресоваться как к байтам, так и к
словам. . К регистрам тоже можно было
адресоваться как к байту, но только к
младшему. А вот команды процессора
всегда были двухбайтными.
Формат
безоперандной команды:
| 15 |
14 |
13 |
12 |
11 |
10 |
09 |
08 |
07 |
06 |
05 |
04 |
03 |
02 |
01 |
00 |
| Код команды |
однооперандной:
| 15 |
14 |
13 |
12 |
11 |
10 |
09 |
08 |
07 |
06 |
05 |
04 |
03 |
02 |
01 |
00 |
| Код команды |
адресация |
РОН |
двухоперандной(src-источник,
dst-приемник):
| 15 |
14 |
13 |
12 |
11 |
10 |
09 |
08 |
07 |
06 |
05 |
04 |
03 |
02 |
01 |
00 |
| Код команды |
адресация
src |
РОН |
адресация
dst |
РОН |
Из
вышеуказанного сразу видно, почему
на этих машинах применялась не
шестнадцатеричная, а восьмеричная
система представления данных - одной
цифрой кодировались три разряда, и
все получалось весьма наглядно. А
наглядность была очень нужна, когда
надо было править код ручками.
Но
самое достойное описания в том
процессоре - это методы адресации.
Надеюсь, ничего не напутаю за
давностью...
Методы
адресации процессора М2
Двоичный
код адресации |
Название |
Описание |
Пример |
| 000 |
Регистровый |
Операнд находится в
регистре |
mov R0,R4 |
| 010 |
Автоинкрементный |
В регистре находится
адрес операнда, после
выполнения регистр
увеличивается на 1(байтовая
операция) или 2(словная) |
mov R0,(R4)+ |
| 100 |
Автодекрементный |
То же, но регистр
уменьшается ДО выполнения
команды |
mov R0,-(R4) |
| 110 |
Индексный |
Адресом операнда
является сумма регистра и
следующего за командой слова |
mov R0, 10(R4) |
| 001 |
Косвенно- регистровый |
Адрес операнда в
регистре |
mov R0,(R4)
или
mov R0,@R4 |
| 011 |
Косвенно-
автоинкрементный |
В регистре находится
адрес адреса (!), после
выполнения команды регистр
инкрементируется аналогично
коду 010 |
mov R0,@(R4)+ |
| 101 |
Косвенно-
автодекрементный |
Аналогично коду 100 |
mov R0,@-(R4) |
| 111 |
Косвенная индексация |
Адресом адреса
операнда является сумма
регистра и следующего за
командой слова |
mov R0,@10(R4) |
| Следующие
режимы адресации можно
выделить как специальные,
поскольку в качестве регистра в
них используется R7 (PC),
указывающий на адрес
инструкции, подлежащей
исполнению |
| 010 111 (278) |
непосредственная |
операнд следует за
словом инструкции. По сути, это
автоинкрементная адресация с иcпользованием
PC |
mov #1,R0 |
| 011 111 (378) |
абсолютная |
слово, следующее за
словом команды, является
абсолютным адресом операнда |
mov R0,@#1000 |
| 110 111 (678) |
относительная |
адресом операнда
является сумма PC и смещения в
следующем за командой слове.
Код получается перемещаемый! |
mov R0,ADRES |
| 111 111 (778) |
Относительно-
косвенная |
Адрес адреса операнда
вычисляется как сумма PC и
следующего за командой слова |
mov R0,@ADRES |
Система команд
процессора М2
|
|
(B)
- команда может выполняться со словом
или байтом, определяется старшим
битом команды. В графе "Код" он
обозначен звездочкой *
R
- регистр общего назначения
SS
- 6 разрядов, определяющих источник
DD
- 6 разрядов, определяющих приемник
XXX
- 8 разрядов смещения в инструкциях
ветвления
ССП
- слово состояния процессора
NN
- 6-ти битное смещение
|
|
| Мнемоника |
Код (8-чный) |
Наименование |
| HALT |
000000 |
Останов - переход в режим
клавиатурного монитора |
| WAIT |
000001 |
Ожидание прерывания |
| RTI |
000002 |
Возврат из прерывания |
| BPT |
000003 |
Прерывание отладки (точка
останова) |
| IOT |
000004 |
Прерывание для ввода-вывода |
| RESET |
000005 |
Сброс (формирование сигнала "сброс"
на шине) |
| RTT |
000006 |
Возврат из прерывания с
установленным T-разрядом ССП -
это использовалось вроде в
отладчиках |
| JMP |
0001DD |
Безусловный переход |
| RTS |
00020R |
Возврат из подпрограммы |
| JSR |
004RDD |
Обращение к подпрограмме.
Работала очень хитро, см.
описание ниже! |
| EMT |
104000- 104377 |
Командное прерывание |
| TRAP |
104400- 104777 |
Командное прерывание |
| NOP |
000240 |
Нет операции. На самом деле это
команда "очистить никакой
разряд слова состояния
процессора", см. далее |
| CLC |
000241 |
Очистка "С" разряда ССП (слова
состояния процессра) |
| CLV |
000242 |
Очистка соответствующих
разрядов ССП. Вообще-то можно
очищать сразу несколько,
определяется четырьмя младшими
битами команды. А если никаких не
очищать - получится NOP |
| CLZ |
000244 |
| CLN |
000250 |
| SEC |
000261 |
Абсолютно аналогично
командам очистки |
| SEV |
000262 |
| SEZ |
000264 |
| SEN |
000270 |
| SWAB |
0003DD |
Перестановка младшего и
старшего байт |
| CLR(B) |
*050DD |
Очистка |
| COM(B) |
*051DD |
Инвертирование |
| INC(B) |
*052DD |
Инкремент |
| DEC(B) |
*053DD |
Декремент |
| NEG(B) |
*054DD |
Изменение знака |
| ADC(B) |
*055DD |
Прибавление переноса |
| SBC(B) |
*056DD |
Вычитание переноса |
| TST(B) |
*057DD |
Проверка - по сути, установка
признаков по содержимому DD. Дело
в том, что команда пересылки
изменяла признаки N и Z ССП! Что
вообще-то странно. |
| ROR(B) |
*060DD |
Циклический сдвиг вправо через
C разряд |
| ROL(B) |
*061DD |
То же влево |
| ASR(B) |
*062DD |
Арифметический сдвиг вправо (деление
на 2) |
| ASL(B) |
*063DD |
То же влево (умножение на 2) |
| MARK |
0064NN |
Восстановление SP - никогда эту
команду не использовал. Что-то
мудреное :-) |
| SXT |
0067DD |
Расширение знака |
| MTPS |
1064SS |
Запись ССП / Чтение ССП.
Учитывая изменение ССП командой
пересылки, этими командами
приходилось пользоваться часто |
| MFPS |
1067DD |
| MOV(B) |
*1SSDD |
Пересылка. Кроме изменения ССП,
была еще одна тонкость -
пересылка байта в регистр
вызывала автоматическое
расширение знака |
| CMP(B) |
*2SSDD |
Сравнение |
| BIT(B) |
*3SSDD |
Проверка разрядов (логическое И,
не изменяя операндов) |
| BIC(B) |
*4SSDD |
Очистка бит |
| BIS(B) |
*5SSDD |
Установка бит |
| XOR |
074RDD |
Исключающее ИЛИ |
| ADD |
06SSDD |
Сложение (работает только со
словами, как и вычитание) |
| SUB |
16SSDD |
Вычитание |
| BR |
0004XXX |
Ветвление безусловное. Во всех
инструкциях ветвления младший
байт команды представляет число
со знаком, определяющее
расстояние передачи управления. |
| BNE |
0010XXX |
Ветвление, если не равно |
| BEQ |
0014XXX |
Ветвление, если равно |
| BGE |
0020XXX |
Ветвление, если больше или
равно |
| BLT |
0024XXX |
Ветвление, если меньше |
| BGT |
0030XXX |
Ветвление, если больше |
| BLE |
0034XXX |
Ветвление, если меньше или
равно |
| BPL |
1000XXX |
Ветвление, если плюс |
| BMI |
1004XXX |
Ветвление, если минус |
| BHI |
1010XXX |
Ветвление, если больше (беззнаковое) |
| BLOS |
1014XXX |
Ветвление, если меньше или
равно (беззнаковое) |
| BVC |
1020XXX |
Ветвление, если нет
переполнения |
| BVS |
1024XXX |
Ветвление, если переполнение |
| BHIS |
1030XXX |
Ветвление, если больше или
равно (беззнаковое) |
| BLO |
1034XXX |
Ветвление, если меньше (беззнаковое) |
| SOB |
077RNN |
Декремент регистра и ветвление,
если не 0. NN - 6 разрядов, ветвление
всегда назад |
| MUL |
070RSS |
Целочисленное умножение. Если
регистр R четный, то в R младшая
часть результата, а в R+1 старшая.
Если R нечетный - только младшая
часть результата |
| DIV |
071RSS |
Целочисленное деление, регистр
R обязательно четный. В R+1 старшая
часть делимого и остаток после
операции. |
| ASH |
072RSS |
Арифметический сдвиг на N
разрядов (N - 5 разрядов + знак) |
| ASHC |
073RSS |
Арифметический сдвиг на N
разрядов двойного слова |
| FADD |
07500R |
Операции с плавающей
запятой. Насколько помнится, R
указывал на блок из 4-х слов, в
котором размещались два числа в
формате с плавающей запятой.
Точнее не помню. Да, команды,
начиная с ASH, были не во всех - в
процессоре M1 их точно не было. |
| FSUB |
07501R |
| FMUL |
07502R |
| FDIV |
07503R |
Вроде
все... Надеюсь, ничего не забыл. И
хотелось бы еще остановиться на
команде перехода на подпрограмму,
поскольку она была, скажем так, не
совсем обычна...
JSR Rn, адрес
По
этой команде:
1) содержимое Rn заносилось в стек
2) в регистр Rn заносился адрес
возврата (следующая команда после JSR)
3) адрес перехода заносился в PC
Так
что привычный CALL (JSR PC) являлся по сути
частным случаем. Если же учесть, что
адрес перехода мог задаваться любым
методом адресации, то извратиться
можно было как угодно. Например,
одной командой очистить все ОЗУ
машины! В стек заносился адрес верха
памяти+2, в нулевой адрес памяти
заносилось 004016 (JSR R0,@SP), в регистр R0
заносился 0 и "программа"
запускалась.
R0
записывался в стек, то есть в верхнюю
ячейку памяти, а в PC заносился адрес,
взятый из стека, то есть тот же ноль и
команда выполнялась снова. Стек
заполнялся нулями до тех пор, пока не
доходил до нулевого адреса, тем самым
записывая команду HALT и делая переход
на нее же. Выполнение программы на
этом останавливалось.
Или,
например, такая команда:
JSR PC,@(SP)+
Она
обеспечивает передачу управления на
адрес из вершины стека, оставив там
же свой адрес возврата, что позволяет
двум подпрограммам передавать
управление друг другу в любом месте!
Для этого нужно только занести в стек
адрес начала одной и передать
управление другой. И можно делать
параллельные процессы :-)
|
|