Microcode Assembler · besm6
Об'єднаний інститут ядерних досліджень Лабораторія обчислювальної техніки та автоматизації
У процесі створення ЕОМ, які працюють за принципом мікропрограмного управління, досить трудомісткою роботою є підготовка мікропрограм. Крім того, для скорочення термінів розробки в цілому виготовлення мікропрограм необхідно вести паралельно з виготовленням апаратури, використовуючи крос-засоби на інструментальних ЕОМ. До таких крос-засобів належить і описувана тут крос-система МІКРОБ, що працює на ЕОМ БЭСМ-6.
Такий підхід уражає т.зв. Горизонтальне програмування. При цьому мікроасемблер, по суті, є генератором бітових рядків постійної довжини. Універсальність його полягає у здатності налаштовуватися на заданий формат мікрокоманди.
Архітектура крос-системи МІКРОБ
Крос-система МІКРОБ має багато спільного з "дорослими" системами програмування мовами високого рівня:
- допускається роздільна трансляція підпрограм;
- результат трансляції записується до бібліотеки модулів завантаження;
- для отримання готової двійкової програми використовується завантажувач, що зв'язує;
===== 1. Виклик транслятора ===== Пакет завдання, що запускається на БЭСМ-6 з метою трансляції мікропрограм, виглядає так:
MICROB – вхід для трансляції. При цьому вважається, що опис формату мікрокоманди (т.зв. глобальний контекст) вже записано в архів асемблера.
MICINI – вхід при спочатку порожньому архіві. При цьому текст, що підлягає трансляції, передує опису формату мікрокоманди.
2. Трансляція глобального контексту
Глобальний контекст мікропрограми складається з
- описи форматумікрокоманди;
- визначення світових імен;
- описи констант із ПЗУ;
Глобальний контекст оформляється у вигляді псевдопрограми, що має ім'я DEFINE:
Тут N задає розрядність мікрокоманди, К - розрядність ПЗП констант. Біти в мікрокоманді нумеруються праворуч наліво: N, N-1, . 2.1. При невказанні К = 64.
Всередині псевдопрограми DEFINE знаходяться інструкції, що визначають поля мікрокоманди та глобальні імена, які вважаються в усіх мікропрограмах.
Декілька зауважень термінологічного характеру:
- - ціле десяткове, якщо немає спеціальних застережень;
- - ідентифікатор у сенсі алгола, довжиною трохи більше 6 символів;
- - Перелік термів, відокремлених один від одного знаками "+" або "-";
- - Число, ім'я або спеціальний символ "*";
Все-таки надалі, заради стислості, ми називатимемо значенням вираження суму його термів, узятих зі своїми знаками. Терми, що входять у вираз, можуть бути трьох типів:
У правильному вираженні має виконуватися співвідношення
2.1. Формат мікрокоманди
Крім розрядності N формат мікрокоманди характеризується ще набором полів, її складових. Для опису одного поля служить інструкція FIELD:
- N1, N2 - числа, що задають ліву та праву межу поля (у будь-якому порядку);
- N3 - вираз, значення якого задає початковий вміст поля. При невказанні N3 вважається банкрутом;
Допускається вкладення одних полів в інші, перекриття полів не допускається (аналогічно до фортранних DO - циклів). Порядок опису полів
Для поля коду операції секвенсора як параметр N3 необхідно вказувати маркуючу конструкцію /С/
2.2. Визначення глобальних імен
Глобальні імена визначаютьсяза допомогою інструкцій EQU та BLOCK:
Тут нове визначається як число, що дорівнює значенню . Трансляція глобального контексту провадиться за один прохід, тому всі імена, що входять до , повинні бути вже визначені.
Це спосіб "групового" визначення імен, аналогічний фортранівському common-блоку. має бути вже визначено.
У лівій частині інструкції BLOCK дозволено вказувати шістнадцяткові числа з префіксом "*":
Шістнадцяткові числа у правій частині інструкції (що входять як терми у вирази) забезпечуються префіксом "$" /долар/).
2.3. Опис констант із ПЗУ
Розрядність всіх констант однакова. Вона задається в інструкції DEFINE. Ліві нулі у константах можна опускати.
2.4. Трохи про синтаксис
На одній карті є одна інструкція. Формат - не фіксована інструкція може починатися з будь-якої позиції картки. Прогалини, власне кажучи, є роздільниками. Прогалини між роздільником та початком наступної лексеми ігноруються. Розділювачі: двокрапка, крапка з комою, кома, плюс, мінус. Загальний формат інструкції:
Недовгий досвід роботи з мікроассемблером показав, що часто для розміщення інструкції однієї карти не вистачає. Тому прийнято таке рішення: символ ">", що знаходиться в першій позиції, означає, що ця карта є продовженням попередньої. Асемблер здатний "заглядати вперед" по файлу читання. Виявивши ">" У першій позиції наступної карти він просто "підклеює її в хвіст" поточної. Число карт продовження – не більше 20.
3. Трансляція мікропрограм
Вся мікропрограма складається з окремих блоків – підпрограм. Допускається роздільна трансляція підпрограм. Результатом трансляції є модуль завантаження, записаний бібліотеку об'єктних модулів. Прицьому, якщо в бібліотеці вже була програма з таким самим ім'ям, то стара версія знищується (аналогічно бібліотекам у моніторній системі "дубна"). При трансляції використовується глобальний контекст, що вже є в архіві. Перерахуємо тепер синтаксичні конструкції, з яких складається підпрограма:
характеристика - це шістнадцяткове число, інтерпретацією якого займатиметься лише завантажувач. На трансляцію програми її характеристика не впливає.
ці конструкції "працюють" так само, як у 2.2.
початковим станом заданого поля вважається значення у правій частині інструкції. Інструкція "працює" тільки в межах підпрограми, що транслюється. При переході до наступної підпрограми асемблер знову отримує інформацію про початкові значення полів з глобального контексту.
код мікрооперації (його ще іноді називають кодом операції секвенсора). Це символічне ім'я, визначене у глобальному чи локальному контексті.
асемблер підставляє значення імені в полі мікрокоманди, яке позначено маркуванням /С/. (Див. 2.1).
Заповнення інших полів мікрокоманди виробляється за загальним алгоритмом, виходячи з правої частини мікрокоманди. Елементи списку задаються в довільному порядку і відокремлюються один від одного комами. Кожен елемент списку представляється або парою:
або просто ім'ям поля (для однобітових полів). Якщо у списку якесь поле не вказано, то в команду заноситься початкове значення цього поля, вказане вказівкою VALUE або взяте з глобального контексту.
Тут можливі неоднозначності за наявності вкладених полів. Для визначеності прийнято таке рішення: незаповнені поля проглядаються в порядку зменшення їх ширини (тобто відстані між лівою та правою межами). Далі, якщо поленабуло значення, то заповненими вважаються і всі вкладені в нього поля.
Розглянемо маленький фрагмент мікропрограми. При цьому ми скористаємось глобальним контекстом, описаним у (2.4).
Поле SEQV (воно відзначено маркуванням /С/ ) заповнюється у першій команді кодом 1 (test=1), а в другій та третій - кодом 0 (jump=0).
У полі АЛУ потрапить у першому випадку код 2, у третьому - код 3. Для другої команди "спрацює" правило замовчування, і поле АЛУ потрапить код 0.
Поле CI у всіх трьох командах одно 1. У першій команді воно явно зазначено у списку полів (наявність імені однобітового поля у списку тягне заповнення кодом 1). У решті команд воно заповниться "1" за замовчуванням.
Якби нам потрібно було при умовчанні вважати CI = 0, слід змінити початкове значення цього поля за допомогою інструкції value:
3.1. Управління печаткою лістингу
Карта *nо list , яка зустрілася в будь-якому місці тексту програми, відключає друк листингу. Карта full list, що зустрілася в будь-якому місці тексту програми, включає друк листингу. Помилкові карти друкуються безумовно.
Лістинг програми друкується рядками завширшки 128 позицій. Рядок відповідає одній інструкції мікроассемблера. Формат рядка:
Якщо інструкція не вміщується в 128 позицій, проводиться перенесення в наступний рядок лістингу, причому поля а-l друкуються порожніми. Перенесення здійснюється на межі елементів списку полів мікрокоманди.
При помилках у програмі помилковий фрагмент відзначається символом "*" у наступному рядку лістингу. У більшості випадків місцезнаходження помилки відзначається з точністю до символу, у крайньому випадку - з точністю до лексеми.
3.3. Семантичний контроль мікрокоманд
У загальному випадку, асемблер "не знає" сенсуокремих полів мікрокоманди та логіки їх взаємодії. Проте найпростіші семантичні правила ми можемо поставити йому. Правила поміщаються перед текстом першої з трансльованих мікропрограм і працюють до кінця файлу. Поки що правил тільки 2:
наприклад, правило: flist тур = тур1, тур2, тур7 означає, що у вираз, що задає значення поля тур можуть входити терми тур1, тур2, тур7 і тільки вони. Якщо якийсь мікрокоманді зустрінеться фрагмент тур=тур4 , це вважатиметься помилкою. Якщо список не вміщується у вхідному рядку, залиште там останню кому, і продовжуйте список з нового рядка. Обмеження кількості правил "flist": сумарна довжина всіх списків - трохи більше 1500.
Діагностика "семантична помилка" забезпечується номером порушеного семантичного правила. Крім того, символ "*" вказує на позицію сканера вхідного рядка в момент останнього порушення правила.
Часті фрагменти мікрокоманд можна описати один раз у вигляді макровизначення. Макровизначення розміщуються у вхідному файлі серед семантичних правил (відносний порядок - несуттєвий) до початку першої програми, що транслюється. Макровизначення займає рівно один рядок і виглядає так:
ім'я макросу не більше ніж із 6 символів. У тексті, що замінює, всі символи істотні, крім хвостових пробілів. Звідси випливає можливість порожніх макросів, коли в тексті, що замінює, немає жодного символу, відмінного від пробілу. Макровизов здійснюється вказівкою в потрібному місці тексту мікрокоманди імені макросу, обрамленого символом "%". Приклад:
Усього може бути до 400 макросів. Сумарний обсяг замінних текстів – до 24000 символів. Повторне визначення макросу не контролюється.
Повторне використання одного і того ж індексу в ПНА контролюєтьсязавантажувачем. Індекси задаються у діапазоні від 0 до ffff.
4. Архів крос-системи
Розподіл віртуальної пам'яті:
- 0 – код наявності глобального контексту;
- 1 - розрядність мікрослова N;
- 2 - найближче до N зверху число, кратне 4;
- 3 - довжина мікрослова в словах Бесм-6;
- 4 - розрядність ПЗП та кількість констант;
- 5 - покажчик вільного місця у архіві;
- 6 – початок таблиці імен;
- 7 – довжина таблиці імен;
- 8 – початок списку констант;
- 20 – таблиця імен;
Елемент таблиці імен займає 5 слів. Робота з таблицею проводиться методом хешування, причому як ключ пошуку використовуються ідентифікатор і тип об'єкта:
- Тип = 1 – локальне ім'я. Після закінчення трансляції підпрограми всі локальні імена вилучаються з таблиці.
- Тип = 2 - глобальне ім'я чи опис пзу-константи;
- Тип = 3 - Опис поля. Глобальні імена та описи полів з'являються у таблиці під час трансляції глобального контексту і живуть там у час існування архіву.
- Тип = 4 - опис підпрограми;
- Тип = 5 - Опис entry-входу.
Крім того, у цьому ж списку зберігаються і імена локальних міток програми, що переписуються туди з таблиці імен після закінчення трансляції. Це зроблено про запас, для зручності роботи з інтерпретатором, буде з'явитися в складі нашої крос-системи.
Вільна пам'ять в архіві використовується як робоча область. Зокрема, асемблер використовує її для зберігання тексту програми, що транслюється (схема трансляції - двопрохідна). Каталог архіву може бути роздрукований за директивою
В останньому випадку видається ще й вміст п з у констант. Виняток програми з архіву робиться за допомогою директиви
5.Отримання двійкової програми
Для отримання двійкової програми використовується завантажувач, що зв'язує. Пакет завдання у разі виглядає так:
Зрозуміло, викликати завантажувач можна відразу після закінчення трансляції тексту програми.
Таблиця завантаження друкується у тому вигляді, як і таблиця завантаження моніторної системі " дубна " . І так само, у списку завантаження можуть друкуватись діагностичні повідомлення:
Список завантаження формується у common-блоці
Для зв'язку із системою моделювання ПУЛЬС є другий вхід у завантажувач:
- nр – ім'я головної підпрограми;
- nа – ім'я архіву системи ПУЛЬС;
- nо - ім'я об'єкта в архіві;
Ще один вхід у завантажувач зроблений для передачі готової програми в пультовий процесор МКБ-8601 (поки це iвм рс/хт к.227):
ПНА можна вивести з архіву за картою
Де N – номер ПНА = 0,1,2. 8 ТУР = high чи low - визначає, який байт виводити: старший (high) чи молодший (low).