У ці пакети входять транслятори, компонувальники, отладчики і інші.
У цій роботі для отримання об'єктного модуля вихідний файл піддається трансляції за допомогою програми tasm.exe з пакету TASM.
Після усунення помилок можна приступати до наступного кроку - створення виконуваного (завантажувального) модуля, або, як ще називають цей процес, до компонування програми. Головна мета цього кроку - перетворити код і дані в об'єктних файлах у їх переміщуване виконується відображення. Процес створення виконуваного модуля поділяють на 2 кроки - трансляцію і компоновку. Це зроблено навмисно для того, щоб можна було об'єднувати разом кілька модулів (написаних на одному або декількох мовах). Формат об'єктного файлу дозволяє, при певних умовах, об'єднати декілька окремо відтранслювати вихідних модулів в один модуль. При цьому у функції компонувальника входить вирішення зовнішніх посилань (посилань на процедури і зміни) в цих модулях. Результатом роботи компонувальника є створення завантажувального файлу з розширенням ехе. Після цього операційна система може завантажити такий файл і виконати його.
Усунення синтаксичних помилок ще не гарантує того, що програма буде хоча б буде запускатися, не кажучи вже про правильність роботи. Тому
обов'язковим етапом процесу розробки є налагодження.
На етапі налагодження, використовуючи опис алгоритму, виконується контроль правильності функціонування як окремих ділянок коду, так і всієї програми в цілому. Але навіть успішне закінчення налагодження ще не є гарантією того, що програма буде працювати правильно з усіма можливими вихідними даними. Тому потрібно обов'язково провести тестування програми, тобто перевірити її роботу на «прикордонних» і свідомо некоректних вихідних даних. Для цього складаються тести.
Специфіка програм на асемблері полягає в тому, що вони інтенсивно працюють з апаратними ресурсами комп'ютера. Ця обставина змушує програміста постійно відстежувати вміст певних регістрів і областей пам'яті. Природно, що людині важко стежити за цією інформацією з великим ступенем деталізації. Тому для локалізації логічних помилок у програмах використовують спеціальний тип програмного забезпечення - програмні відлагодження.
Відладчики бувають двох типів:
• інтегровані - відладчик реалізований у вигляді інтегрованого середовища типу середовища для мов Turbo Pascal, Quick С і т.д.;
• автономні - відладчик являє собою окрему програму.
Через те, що асемблер не має своєї інтегрованого середовища, для налагодження написаних на ньому програм використовують автономні відлагодження. До теперішнього часу розроблено велику кількість таких отладчиков. У загальному випадку за допомогою автономного отладчика можна досліджувати роботу будь-якої програми, для якої було створено виконуваний модуль, незалежно від того, якою мовою був написаний його вихідний текст.
2. Опис програмної моделі
Пропозиції, складові програму, можуть являти собою синтаксичну конструкцію, що відповідає команді, макрокоманді, Директиві або коментарю. Для того щоб транслятор асемблера міг розпізнати їх, вони повинні формуватися за певними синтаксичним правилам.
Пропозиції асемблера формуються з лексем, що представляють собою синтаксично нероздільні послідовності припустимих символів мови мають сенс для транслятора. Лексемами є:
• ідентифікатори - послідовності припустимих символів, що використовуються для позначення таких об'єктів програми, як коди операцій, імена змінних і назви міток. Правило запису ідентифікаторів полягає в наступному. Ідентифікатор може складатися з одного або декількох символів. В якості символів можна використовувати букви латинського алфавіту, цифри і деякі спеціальні знаки - _,?, $, @.
• ланцюжка символів - послідовності символів, укладені в одинарні або подвійні лапки;
• цілі числа в одному з наступних систем числення: двійковій, десятковій, шістнадцятковій. Ототожнення чисел при записі їх у програмах на асемблері виробляється за певними правилами. Десяткові числа не вимагають для свого ототожнення зазначення будь-яких додаткових символів.
Практично кожне речення містить опис об'єкта, над якою або за допомогою якого виконується певна дія. Ці об'єкти називаються операндами. Їх можна визначити так: операнди - це об'єкти (деякі значення, регістри або комірки пам'яті), на які діють інструкції чи директиви, або це об'єкти, які визначають або уточнюють дію інструкцій або директив.
Операнди можуть комбінуватися з арифметичними, логічними, побітовим і атрибутивними операторами для розрахунку деякого значення або визначення комірки пам'яті, на яку буде впливати дана команда або директива.
Розглянемо класифікацію операндів, підтримуваних транслятором асемблера.
Постійні або безпосередні операнди - число, рядок, ім'я або вираз, мають деяке фіксоване значення. Ім'я не повинно бути переміщуваним, тобто залежати від адреси завантаження програми в па ¬ м'яти.
Адресні операнди - задають фізичне розташування операнда в пам'яті за допомогою вказівки двох складових адреси: сегмента і зсувів (рис. 2.2).
Рис. 2.2. - Синтаксис опису адресних операндів
Переміщувані операнди - будь-які символьні імена, що представляють деякі адреси пам'яті. Ці адреси можуть позначати місце розташування в пам'яті деякої інструкції (якщо операнд - мітка) або даних (якщо операнд - ім'я області пам'яті в сегменті даних). Переміщувані операнди відрізняються від адресних тим, що вони не прив'язані до конкретного адресою фізичної пам'яті. Сегментна складова адреси переміщуваного операнда невідома і буде визначена після завантаження програми в пам'ять для виконання.
Зчитувач адреси - специфічний вид операнда. Він позначається знаком $. Специфіка цього операнда в тому, що коли транслятор асемблера зустрічає у вихідній програмі цей символ, то він підставляє замість нього поточне значення лічильника адреси. Значення лічильника адреси, або як його іноді називають лічильник розміщення.
Базовий і індексний операнди. Цей тип операндів використовується для реалізації непрямої базової, непрямої індексної адресації або їх комбінацій і розширень.
Операнди є елементарними компонентами, з яких формується частина машинної команди, що позначає об'єкти, над якими виконується операція. У більш загальному випадку операнди можуть входити як складові частини в більш складні утворення, звані виразами. Вирази являють собою комбінації операндів та операторів, що розглядаються як єдине ціле. Результатом обчислення виразу може бути адреса деякої комірки пам'яті або деяке константне (абсолютне) значення. У табл. 2.2 наведено підтримувані мовою асемблера оператори і перераховані їх пріоритети.
Оператор перевизначення типу ptr застосовується для перевизначення або уточнення ім'я типу мітки або змінної, що визначаються виразом. Тип може приймати одне з наступних значень: byte, word, dword, qword, tbyte, noar, far. Оператор ptr дозволяє безпосередньо в команді перевизначити тип і виконати команду.
Оператор перевизначення сегмента: (двокрапка) змушує обчислювати фізичну адресу щодо конкретно задається сегментної складової: «ім'я сегментного регістра», «ім'я сегмента» з відповідної директиви SEGMENT або «ім'я групи».
3. Розробка і реалізація програмного забезпечення
Алгоритм реалізує обчислення CRC8 розподілом заданого масиву даних на який утворює поліном x8 x5 x4 1. Розподіл виконано послідовним відніманням за модулем 2 полінома з вихідної послідовності.
Для цього організовано цикл за словами вихідної послідовності і цикл по розрядного зсуву усередині слова. Оскільки зручніше переглядати масив в порядку збільшення адреси (від молодшого до старшого), процедура реалізує дзеркальний алгоритм.
Докладніше про те як виконується розподіл при обчисленні CRC дивися у доданих джерелах.
Для процедури обчислення вихідні дані передаються через регістри. Сегментний регістр ES повинен містити сегмент в якому розташований масив, регістр DX - зміщення початку масиву всередині сегмента, BX - довжина масиву. Результат накопичується в акумуляторі AL.
Перед початком обчислень ініціюємо AX значенням FFFFh. У регістр CX заносимо довжину масиву і множимо її на 8. Таким чином цей регістр зберігає кількість розрядів в масиві і використовується як лічильник циклів командою loop. Доповнювати вихідну послідовність (перевіряється масив) нулями немає необхідності, тому що кількість розрядів кратно ступеня утворює многочлена.
Зсув переносимо в регістр DI.
У BX заносимо перше слово масиву.
Перевіряємо молодший розряд BX. Якщо він дорівнює нулю - виконуємо зрушення слова на один розряд вправо, якщо немає - виконуємо додавання з утворюючим многочленом за модулем 2, а потім виконуємо зрушення.
Зрушення за розрядами виконується наступним чином. У DX зберігається кількість зрушень що залишився до кінця слова (зручніше підраховувати не кількість виконаних зрушень, а від кількості розрядів у слові до 0). Якщо в DX - 0, то потрібно в DX записати 8, а в BX завантажити наступне слово масиву, інакше - просто зрушуємо BX вправо на розряд і зменшуємо DX на 1.
Повторюємо підсумовування.
Після закінчення процедури акумулятор AX містить обчислений для масиву значення CRC8.
Для збереження результату його переносимо в змінну result.
Для перевірки цілісності масиву потрібно повторити обчислення контрольної суми і порівняти зі значенням в result.
Блок-схема алгоритму наведена в додатку 2.