Cистемне програмування
Практична робота № 1
ЗМІШАНЕ ПРОГРАМУВАННЯ НА МОВАХ СІ ТА АСЕМБЛЕР
Труднощі опису зв'язку програм мовою C і асемблерних програм полягає в тому, що різні версії мови C мають різні угоди про зв'язки і для більш точної інформації варто користатися посібником з наявної версії мови C.
Більшість версій мови C забезпечують передачу параметрів через стек у зворотній (у порівнянні з іншими мовами) послідовності. Звичайно доступ, наприклад, до двох параметрів, переданих через стек, здійснюється в такий спосіб:
MOV ES,BP
MOV BP,SP
MOV DH,[BP+4]
MOV DL,[BP+6]
...
POP BP
RET
Деякі версії мови C розрізняють прописні і рядкові букви, тому ім'я асемблерного модуля повинне бути представлено в тому ж символьному регістрі, який використовують для посилання C-програми.
У деяких версіях мови C потрібно, щоб асемблерні програми, що змінюють регістри DI і SI, записували їхній вміст у стек при вході і відновлювали ці значення зі стека при виході.
Ассемблерні програми повинні повертати значення, якщо це необхідно, у регістрі AX (одне слово) чи в регістро парі DX:AX (два слова).
Для деяких версій мови C, якщо ассемблерна програма встановлює прапор DF, те вона повинна скинути його командою CLD перед поверненням.
Щоб скомпонувати разом модулі Borland C++ і Турбо Асемблера, повинні бути дотримані наступні три пункти:
У модулях Турбо Асемблера повинні використовуватися угоди про імена, прийняті в Borland C++.
Borland C++ і Турбо Асемблер повинні спільно використовувати відповідні функції й імена змінних у формі, прийнятної для Borland C++.
Для комбінування модулів у виконувану програму потрібно використовувати утіліту-компоновщик TLINK.
Важливою концепцією С++ є безпечне, з погляду узгодження типів, компонування. Компілятор і компоновщик повинні працювати узгоджено, щоб гарантувати правильність типів переданих між функціями аргументів. Процес, названий "коректуванням імен" (name-mangling), забезпечує необхідну інформацію про типи аргументів. "Коректування імені" модифікують ім’я функції таким чином, щоб воно несло інформацію про аргументи, що приймаються функцією.
Коли програма пишеться цілком на С++, коректування імен відбувається автоматично і прозоро для програми. Однак, коли ви пишете асемблерний модуль для наступного його компонування з програмою на С++, ви самі зобов’язані забезпечити коректування імен у модулі. Це легко зробити, написавши порожню функцію на С++ і скомпілювавши її з асемблерным модулем. Згенерований при цьому Borland С++ файл .ASM буде містити виправлені імена. Потім ви можете їх використовувати при написанні реального асемблерного модуля.
Щоб дана функція Асемблера могла викликатися з С++, вона повинна використовувати ту ж модель пам’яті, що і програма мовою С++, а також сумісний із С++ сегмент коду. Аналогічно, щоб дані, визначені в модулі Асемблера, були доступні в програмі мовою С++(чи дані С++ були доступні в програмі Асемблера), у програмі на Асемблері повинні дотримуватися угоди мови С++ по найменуванню сегмента даних.
Моделі пам’яті й обробку сегментів на Асемблері може виявитися реалізувати досить складно. На щастя, Турбо Асемблер сам виконує майже всю роботу по реалізації моделей пам’яті і сегментів, сумісних з Borland C++, при використанні спрощених директив визначення сегментів.
Спрощені директиви визначення сегментів і borland c++
Директива .MODEL указує Турбо Асемблеру, що сегменти, створювані за допомогою спрощених директив визначення сегментів, повинні бути сумісні з обраною моделлю пам’яті (TINY - крихітної, SMALL - малої, COMPACT - компактної, MEDIUM - середньої, LARGE великий чи HUGE - величезної) і керує призначуваним за замовчуванням типом (FAR чи NEAR) процедур, створюваних по директиві PROC. Моделі пам’яті, визначені за допомогою директиви .MODEL, сумісні з моделями Borland C++ з відповідними іменами.
Нарешті, спрощені директиви визначення сегментів ....