Макрокоманди всередині макровизначень

На відміну від попереднього, цей засіб може бути дуже корисним. Насамперед — для макрокоманд, що часто вживаються, можуть бути включені в бібліотеки макровизначень — системні або користувальницькі. Це може спростити створення нових макровизначень.

Для забезпечення такої можливості достатньо зробити рекурсивним лише 2-й прохід макропроцесора. У ньому дещо ускладнюється аналіз операторів макровизначення. У галузі «Інший» (на нашій схемі алгоритму вона починається з блоку) 2-й прохід макропроцесора повинен розпізнавати макрокоманду і, якщо оператор — макрокоманда, викликати сам себе. Розпізнавання макрокоманди методом виключення: якщо оператор не оператор Макромови, не директива Асемблера і не машинна команда, то він вважається макрокомандою і шукається в Таблиці імен макровизначень. Для рекурсивного виклику створюється нова Таблиця локальних змінних (і параметрів). Таблиця глобальних змінних та індекс унікальних міток використовуються загальні.

Певна складність виникає в тому випадку, якщо вкладені марокоманди - бібліотечні. У нашому алгоритмі 1-го проходу вміст макровизначення (те, що лежить між операторами MACRO і MEND) не аналізувалося, отже, визначення вкладених макрокоманд не заносилися до Таблиці макровизначень та імен макроподолань. Є два варіанти вирішення цієї проблеми:

u На 1-му проході все ж таки розпізнавати вкладені макровиклики і включати макровизначення їх у таблиці.

u Виконувати це на 2-му проході: при появі оператора, не розпізнаного ні як оператор Макромови, ні як директива Асемблера, ні як машинна команда і ні як макрокоманда, визначення якої вже є в наших таблицях, вважати його бібліотечною макрокомандою та шукати її макровизначення у бібліотеках. Якщомакровизначення знайдено, воно додається до наших таблиць. Немає необхідності видаляти з таблиць визначення вкладеної бібліотечної макрокоманди при завершенні обробки зовнішнього макровиклику: воно може знадобитися при обробці та подальших макродзвінків.

Якісне розширення можливостей

Активне та грамотне застосування макрозасобів може зробити роботу програміста досить продуктивною. Так, витративши певні зусилля на створення бібліотеки макровизначень, програміст може перетворити мову Асемблера на якісно нову мову, яка матиме деякі властивості мови високого рівня. Програміст може зробити цю мову певною мірою проблемно-орієнтованою, тобто максимально пристосованою для тих завдань, які вирішує її розробник. Коротко опишемо ті основні напрямки, якими може йти розширення можливостей Асемблера за рахунок макрозасобів.

Структурний асемблер

У вигляді макрокоманд можуть бути реалізовані оператори, близькі до операторів управління потоком обчислення в мовах високого рівня (умовні оператори, розгалуження, різні види циклів). Відомим прикладом такого розширення є мова макроассемблера BCPL - попередник мови C.

Об'єктно-орієнтований Асемблер

Макрозасоби можуть забезпечити і реалізацію властивостей об'єктно-орієнтованого програмування — більшою чи меншою мірою.

Найпростіше розширення асемблера ГО властивостями передбачає введення макрокоманди визначення об'єкта (або резервування пам'яті для об'єкта). У макрокоманді вказується тип об'єкта і використовується замість директив DC/BSS. Для типу можуть бути створені макрокоманди-операції. У цьому варіанті може бути втілений принцип поліморфізму, оскільки одна іта ж операція може бути допустимою для різних типів. (Наприклад, одна команда складання для всіх типів — чисел, незалежно від розрядності та форми подання). Принцип інкапсуляції реалізується тут у тому сенсі, що програміст, який використовує макрокоманди не повинен знати внутрішньої структури об'єкта та подробиці виконання операцій над ним, захист внутрішньої структури організувати набагато складніше.

Є приклади розробок, в яких на рівні Макромови створені і засоби опису класів, що включають успадкування класів з усіма можливостями, що з нього випливають.

Машинна мова, що переноситься

Макрозасобами може бути забезпечений повнофункціональний набір команд певної віртуальної машини. Програма пишеться мовою цієї віртуальної машини. Для різних платформ створюються бібліотеки макровизначень, які забезпечують розширення макровикликів команди цієї цільової платформи. Програма, таким чином, стає переносимою лише на рівні вихідного тексту. Оскільки макровизначення може бути побудовано так, щоб генерувати ненадлишковий код для кожного конкретного виклику, програма на мові віртуальної машини не поступатиметься в ефективності програмі, одразу написаної мовою цільового асемблера.

Основні поняття

Завантажувач - програма, яка готує об'єктну програму до виконання та ініціює її виконання.

Детальніше функції Завантажувача наступні:

u виділення місця для програм у пам'яті (розподіл);

u фактичне розміщення команд та даних у пам'яті (завантаження);

u дозвіл символічних посилань між об'єктами (зв'язування);

u передача управління на вхідну точку програми (ініціалізація).

Не обов'язково функції Завантажувача повиннівиконуватися саме в тій послідовності, як вони описані. Опишемо ці функції докладніше.

Функція розподілу, очевидно зрозуміла з її назви. Для розміщення програми в оперативній пам'яті має бути знайдено та виділено вільне місце у пам'яті.

Для виконання цієї функції Завантажувач зазвичай звертається до операційної системи, яка виконує запит на виділення пам'яті в рамках загального механізму управління пам'яттю.

Функція завантаження зводиться до зчитування образу програми з диска (чи іншого зовнішнього носія) оперативну пам'ять.

u функція завантаження, звичайно, виконується, але вона гранично проста;

u функція переміщення виключається;

u функція ініціалізації залишається.

Частка абсолютних програм у загальній масі програмного забезпечення дуже мала. Абсолютними можуть бути системні програми найнижчого рівня, програми, що записуються в ПЗП, програми для пристроїв, що вбудовуються. Переважна більшість системних і всі прикладні програми переміщуються, тобто, вони можуть завантажуватися для виконання в будь-яку область пам'яті, і Завантажувач для таких програм виконує перераховані функції в повному обсязі.

При розгляді асемблерів ми залишили поза увагою обробку звернень до зовнішніх точок та формат об'єктного модуля. Ці питання безпосередньо відносяться до функцій Завантажувача, і ми розглянемо їх тут.

Основні типи завантажувачів - налаштовують і безпосередньо зв'язують.

Завантажувачі, що настроюють

Завантажувач, що настроює, є першим кроком у бік ускладнення від Абсолютного Завантажувача. Функції зв'язування і переміщення вирішуються у ньому найефективнішим, але найпростішим способом.