Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
LABA07_2012.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
154.62 Кб
Скачать

Засоби системного програмування

Лабораторна робота № 7.

Багатомодульне програмування.

Мета: Оволодіти навиками створення багатомодульних програм. Засвоїти правила взаємодії різних модулів.

Багатомодульне програмування

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

  • є необхідність компонування декількох програм написаних на різних мовах програмування (наприклад, для об’єднання потужності мов високого рівня та ефективності асемблера);

  • програма, написана у вигляді одного модуля, може виявитись завеликою для асемблювання;

  • окремі модулі можуть бути написані різними проектувальниками з метою подальшої інтеграції;

  • з причини великого розміру виконавчого модуля може виникнути необхідність перекриття окремих частин програми в процесі виконання.

Кожна програма асемблюється окремо і генерує власний унікальний об’єктний (OBJ) модуль. Програма ‑ компонувальник (LINK) як правило виконання починається з основної програми, яка викликає одну або декілька підпрограм. Підпрограми, в свою чергу, можуть задіювати інші підпрограми.

Виклик іншої програми зумовлює необхідність міжсегментного (довгого) виклику (CALL). Дана операція спочатку записує до стеку вміст регістру CS і заносить до цього регістру адресу іншого сегменту, потім записує до стеку значення регістру IP і заносить до цього регістру нову відносну адресу.

Таким чином, в стеку запам’ятовуються і адреса кодового сегменту, і зміщення для наступного повернення з підпрограми.

Наприклад, міжсегментний виклик (CALL) може складатись з такого об’єктного коду:

9A 0002 AF04

Машинний код для міжсегментного виклику CALL – 9A. При цьому команда CALL записує значення 0002 у вигляді 0200 до регістру IP, а значення 04AF – до регістру CS. Комбінація цих адрес вказує на першу виконувану команду у програмі, що викликається:

Кодовий сегмент

04AF0

Зміщення в IP

0200

Дійсна адреса

04CF0

При виході з процедури, що викликалась, міжсегментна команда REТ відновлює обидві адреси в регістрах CS і IP і, таким чином, передає управління на наступну після CALL команду.

Розглянемо, наприклад, основну програму MAINPROG та підпрограму, що викликається за допомогою міжсегментного виклику CALL - SUBPROG.

EXTRN SUBPROG : FAR

MAINPROG: .

CALL SUBPROG

....

PUBLIC SUBPROG

SUBPROG: .

....

RET

Команда CALL в основній програмі повинна “знати”, що програма, яка викликається, знаходиться поза межами даного сегменту. Директива EXTRN вказує асемблеру, що посилання на SUBPROG має атрибут FAR, тобто є визначеним в іншому асемблерному модулі. Оскільки сам асемблер не має можливості точно визначити такі посилання, він генерує пустий об’єктний код для наступного його заповнення при компонуванні:

9A 0000 ---- E

Підпрограма SUBPROG містить директиву PUBLIC, що вказує асемблеру і компонувальнику, що інший модуль повинен “знати” адресу SUBPROG. В результаті, після успішного асемблювання програм MAINPROG і SUBPROG в окремих об’єктних модулях, вони можуть бути скомпільовані наступним чином:

D:\HOME\TASM > tasm MAINPROG /l

D:\HOME\TASM > tasm SUBPROG /l

D:\HOME\TASM > tlink MAINPROG + SUBPROG

Компонувальник встановлює відповідності між адресами EXTRN в одному об’єктному модулі з адресами PUBLIC в іншому і заносить необхідні відносні адреси. Потім він об’єднує два об’єктних модуля в один виконавчий.

В разі неможливості розв’язати посилання компонувальник видає повідомлення про помилку.

Директива EXTRN має такий формат:

EXTRN ім’я : тип [, … ]

Можна призначити більше одного імені (до кінця рядка) або закодувати додаткові директиви EXTRN. В іншому асемблерному модулі відповідне ім’я повинно бути визначене і ідентифіковане як PUBLIC. Існують такі типи елементів: ABS, BYTE, WORD, DWORD, FAR, NEAR. Ім’я може бути визначене через EQU і повинно задовольняти реальному визначенню імені.

Директива PUBLIC вказує асемблеру і компонувальнику, що адреса вказаного ідентифікатора є доступною з інших програм. Директива має такий формат:

Public ідентифікатор [, … ]

Можна призначити більше одного ідентифікатора (до кінця рядка) або закодувати додаткові директиви PUBLIC. Ідентифікатори можуть бути мітками (включаючи PROC-мітки), змінними або числами. Неправильними ідентифікаторами є імена регістрів та EQU-ідентифікатори, що призначають більш як двобайтні значення.

Існує декілька способів компонування програм. Кожен з них характеризується одною або декількома такими рисами:

  • директиви EXTRN і PUBLIC в якості міток;

  • спільний кодовий сегмент - шляхом використання директиви PUBLIC в заголовку кодового сегменту кожної з програм, що компонуються;

  • спільні дані.

Використання директив extrn і public в якості міток

Програма, приведена нижче, складається з основної програми MAINPROG та підпрограми SUBMUL. Директива EXTRN в основній програмі визначає SUBMUL як точку входу в підпрограму. Підпрограма містить директиву PUBLIC, яка вказує компонувальнику на те, що точкою входу для виконання є мітка SUBMUL. Підпрограма перемножує вміст регістру AX (значення з поля даних PRICE) на вміст регістру BX (значення з поля даних QTY), при цьому результат операції буде розміщено в регістровій парі DX:AX (в даному випадку – 002E 4000). В підпрограмі відсутній сегмент даних, оскільки вона не визначає ніяких даних.

*Примітка: Для успішного компонування компонувальник потребує знайти хоча б один стековий сегмент. В підпрограмі не визначено стекового сегменту, оскільки вона використовує ті ж самі стекові адреси, що й основна програма. Таким чином, стек, що визначається в основній програмі, є доступним і в підпрограмі.

TITLE CALLMULL ;Головна програма

EXTRN SUBMUL:FAR

STACKSG SEGMENT PARA STACK 'Stack'

DW 64 DUP(?)

STACKSG ENDS

DATASG SEGMENT PARA 'Data'

QTY DW 0140H

PRICE DW 2500H

DATASG ENDS

CODESG SEGMENT PARA 'Code'

BEGIN PROC FAR

ASSUME CS:CODESG,DS:DATASG,SS:STACKSG

PUSH DS

SUB AX,AX

PUSH AX

MOV AX,DATASG

MOV DS,AX

MOV AX,PRICE ;Занести вартість

MOV BX,QTY ; і кількість

CALL SUBMUL ;Викликати підпрограму

RET

BEGIN ENDP

CODESG ENDS

END BEGIN

ТITLE SUBMUL ;Підпрограма множення

CODESG SEGMENT PARA 'Code'

SUBMUL PROC FAR

ASSUME CS:CODESG

PUBLIC SUBMUL

MUL BX ;AX-вартість, BX-кількість

RET ;Добуток в DX:AX

SUBMUL ENDP

CODESG ENDS

END

Використання спільного кодового сегменту

В основній програмі та в усіх підпрограмах, що компонуються разом, необхідно використати атрибут PUBLIC в директиві SEGMENT:

CODESG SEGMENT PARA PUBLIC 'CODE'

В даному випадку з таблиці ідентифікаторів слідує, що узагальнений тип кодового сегменту – PUBLIC. Необхідно зауважити, що карта компонування вказує на наявність в програмі лише одного кодового сегменту - внаслідок того, що заголовки кодових сегментів основної програми та підпрограми співпадають, компонувальник об’єднує їх в один фізичний кодовий сегмент.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]