Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

гос / sp-lect (1)

.pdf
Скачиваний:
18
Добавлен:
16.02.2016
Размер:
2.59 Mб
Скачать

IFNDEF Name

ECHO &Name not defined

.ERR

ENDIF

полягає лише в тому, що за допомогою ECHO в IFNDEF можна сформувати розширений коментар, щодо причин завершення роботи препроцесора замість стандартного «error A2055 : forced error : symbol not defined : Name», що генерується .ERRNDEF.

Приклад 6.4 Наступний приклад демонструє використання деяких з вищерозглянутих макрозаcобів на прикладі задачі обробки одновимірного масиву. Додаток SumaMacro використовує чотири різні макровизначення для знаходження добутку елементів одновимірного масиву з елементами розміром в байт, слово і подвійне слово.

; Файл SumaMacro.inc

SumArray1 MACRO

Name,bwd,reg1,reg2

LOCAL

next

 

push ecx

 

push esi

 

push eax

 

xor ebx,ebx

 

mov ecx,LENGTHOF Name

lea esi,Name

 

next: lods&bwd

 

add reg1,reg2

 

loop next

 

pop eax

 

pop esi

 

pop ecx

 

ENDM

 

 

SumArray2 MACRO

Name,bwd,plus

LOCAL

next

 

FOR Register,<eax,ecx,esi>

push Register

ENDM

xor ebx,ebx

mov ecx,LENGTHOF Name lea esi,Name

next: lods&bwd plus

loop next

FOR Register,<esi,ecx,eax>

pop Register ENDM

ENDM

SumArray3 MACRO Name,sum,type

LOCAL next

FORC r,cda

push e&r&x

ENDM

xor sum,sum

mov ecx,LENGTHOF Name lea edx,Name

next: add sum, type ptr [edx]

add edx,SIZE Name loop next

FORC r,adc

pop e&r&x

ENDM

ENDM

pushl MACRO list:VARARG

FOR operand,<list> push operand

ENDM

ENDM

popl MACRO list:VARARG

FOR operand,<list>

pop operand

ENDM

ENDM

SumArray4 MACRO Name

LOCAL next

IFB <Name>

ECHO Array name required

.ERR ENDIF IFNDEF Name

ECHO &Name not defined

.ERR ENDIF

pushl eax,ecx,esi xor ebx,ebx

mov ecx,SIZEOF Name / SIZE Name lea esi,Name

next:

IF SIZE Name EQ 1

lodsb

add bl,al

ELSEIF SIZE Name EQ 2

lodsw

add bx,ax ELSEIF SIZE Name EQ 4

lodsd

add ebx,eax

ELSE

.ERR ENDIF loop next

popl esi,ecx,eax

ENDM

; Файл SumaMacro.asm

.386

 

.model flat, stdcall

 

option casemap :none

 

include SumaMacro.inc

 

.data

 

ByteArray

db 1,2,3,4,5

WordArray

dw 1,2,3,4,5

DWordArray

dd 1,2,3,4,5

.code

 

start: SumArray1 ByteArray,b,bl,al SumArray1 WordArray,w,bx,ax SumArray1 DWordArray,d,ebx,eax SumArray2 ByteArray,b,<add bl,al> SumArray2 WordArray,w,<add bx,ax>

SumArray2 DWordArray,d,<add ebx,eax>

SumArray3 ByteArray,bl,byte

SumArray3 WordArray,bx,word

SumArray3 DWordArray,ebx,dword

SumArray4 ByteArray

SumArray4 WordArray

SumArray4 DWordArray ret

end start

7 МОДУЛЬНЕ ПРОГРАМУВАННЯ

7.1 Концепція модульного програмування

Уся історія розвитку зaco6iв розробки програм невідємно повязана з намаганнями максимально спростити i полегшити процес програмування. Особливу актуальність ці задачі набули внаслідок зростання обсягів і

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

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

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

1.Розробка та налагодження окремих модулів виконується ізольовано від інших модулів проекту, що дозволяє залучати до його розробки цілі

групи програмістів.

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

Впершу чергу ми приділимо увагу питанням використання асемблерних модулів розроблених з використанням Microsoft Macro Assembler (MASM) в програмах, розроблених з використанням Microsoft Visual C++, але при цьому будуть задіяні й зворотні звязки, бо реалізація асемблерних модулів в свою чергу передбачатиме використання сервісних послуг операційної системи Windows NT, а її компоненти написані переважно на С/С++.

Модульне програмування є подальшим продовженням і розширенням процедурного програмування, і окремою структурною одиницею кожного модуля є підпрограма (процедура, функція).

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

7.2 Конвенції виклику

Конвенції виклику (Calling convention) регламентують способи організації виклику підпрограм, передавання їм параметрів і повернення результатів роботи підпрограм в точку виклику. Конвенції виклику визначають:

1.Місце розташування параметрів підпрограми: а) регістри; б) стек;

в) регістри та стек;

2.Місце розташування повернених результатів.

3.Порядок передавання параметрів

а) при використанні регістрів зіставлення регістрів з номерами параметрів в описі підпрограми;

б) при використанні стека прямий (зліва направо) або зворотний (справа наліво) порядок зіставлення параметрів в описі підпрограми;

4.При використанні для передавання параметрів стеку хто вирівнює стек по завершенні виклику

а) підпрограма; б) код, що викликав підпрограму;

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

Протягом розвитку програмування сформувалося декілька конвенцій виклику серед яких можна зазначити наступні:

1.PASCAL – параметри передаються через стек в прямому порядку (зліва направо), стек вирівнює підпрограма.

2.С (CDECL) і SYSCALL – параметри передаються через стек в зворотному порядку (справа наліво), стек вирівнює код, що викликає підпрограму.

3.STDCALL – параметри передаються через стек в зворотному порядку (справа наліво), стек вирівнює підпрограма.

4. FASTCALL (REGISTER) – не стандартизована і існує в декількох реалізаціях:

а) в реалізації Borland для 32-х розрядних версій Windows NT: перший (зліва направо) параметр в регістрі EAX, другий в EDX, третій в ECX, інші, за наявності таких, розміщуються в стеку в прямому порядку (зліва направо), стек вирівнює підпрограма;

б) в реалізації Microsoft для 32-х розрядних версій Windows NT: перший (зліва направо) параметр в регістрі ECX, другий в EDX, інші, за наявності таких, розміщуються в стеку в зворотному порядку (справа наліво), стек вирівнює підпрограма;

в) в реалізації Microsoft для 64-х розрядних версій Windows NT: для параметрів розміром 8/16/32/64 біта – 1- й (зліва направо) в RCX, 2-й в RDX, 3-й в R8, 4-й в R9. Якщо перші чотири параметри є числами з плаваючою комою, то вони передаються зліва направо в регістрах XMM0–XMM3. Пятий та інші параметри, за наявності таких, розміщуються в стеку в зворотному порядку (справа наліво, тобто від останнього до пятого), стек вирівнює код, що викликає підпрограму;

Конвенції CDECL, STDCALL і FASTCALL для 32-х розрядних версій

Windows NT передбачають повернення результату з підпрограми через регістр- акумулятор за значенням в EAX/AX/AL, якщо його розмір не перевищує 32 біти. Результат розміром 8 байтів повертається за значенням в парі регістрів EDX:EAX, все інше повертається за адресою в EAX. Числа з плаваючою комою повертаються за значенням через верхівку стеку арифметичного співпроцесора.

Серед перерахованих вище, конвенції виклику PASCAL (FORTRAN) і SYSCALL не підтримується сучасними версіями компіляторів Microsoft Visual C++, а MASM безпосередньо не підтримує FASTCALL.

7.3 Конвенції іменування

Функції усередині програм на мовах C й C++ розпізнаються за внутрішніми іменами які в загальному випадку відрізняються від імен функцій

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

удеяких ситуаціях потрібно знати і вміти вказувати внутрішнє ім'я.

Набір правил за якими компілятором створюється внутрішнє імя функції називають конвенцією іменування (Naming convention). Певній конвенції виклику відповідає певна конвенція іменування. Таблиця 7.1 на прикладі функції, визначеної з іменем FunctionName, демонструє як с(по)творюються імена функцій компілятором.

Таблиця 7.1

Конвенція виклику

Імя функції (конвенція іменування)

 

 

 

SYSCALL

FunctionName

 

 

 

 

PASCAL, FORTRAN, BASIC

FUNCTIONNAME

 

 

 

 

С (__cdecl)

_FunctionName

 

 

 

 

STDCALL (__stdcall)

_FunctionName@N, де N –

загальний розмір в

 

байтах параметрів функції

 

 

 

 

__fastcall

@FunctionName@N, де N –

загальний розмір в

 

байтах параметрів функції

 

 

 

 

7.4 Підпрограма як структурна одиниця модуля

Коли в попередніх розділах зазначалося, що Microsoft Macro Assembler чи Microsoft Visual C++ не підтримує ту або іншу конвенцію виклику чи іменування, то малося на увазі те, що вони не мають відповідних вбудованих мовних засобів, які б примусили компілятор чи асемблер автоматично сформувати код функції та/або код її виклику згідно з конвенцією.

Для асемблера таким мовним засобом є розширений синтаксичний опис підпрограми, який для 32-розрядного MASM має наступний вигляд:

ім’я PROC [<Атрибути>] [USES <Регістри>] [<Параметри>]

[LOCAL <Змінні>]

<послідовність команд>

RET

ім’я ENDP

В квадратних дужках «[…]» зазначено необовязкові директиви. <Атрибути> мають наступний синтаксис:

[<відстань>] [<конвенція>] [<видимість>] [<пролог>]

NEAR

С

 

 

 

 

FAR

STDCALL

PRIVATE

NEAR16

SYSCALL

 

<відстань> =

<конвенція>=

<видимість>= PUBLIC

FAR16

PASCAL

 

NEAR32

BASIC

EXPORT

 

 

 

FAR32

FORTRAN

 

Якщо атрибут відстані не зазначений він визначається асемблером автоматично на основі моделі памяті, зазначеної у відповідному параметрі директиви .MODEL. Для моделі FLAT атрибут відстані буде NEAR і його можна не зазначати.

Атрибут <конвенція> визначає конвенцію виклику (та іменування) згідно з якою асемблер буде генерувати код прологу, і, як наслідок, код епілогу підпрограми.

Якщо атрибут конвенції не зазначений він визначається асемблером автоматично на основі конвенції, зазначеної у відповідному параметрі директиви .MODEL (STDCALL для .MODEL FLAT, STDCALL).

Якщо конвенція виклику не зазначена ні в директиві .MODEL, ні в описі підпрограми, то використання усіх можливостей розширеного синтаксису опису підпрограми стає неможливим.

Атрибути конвенції PASCAL, BASIC і FORTRAN є абсолютно еквівалентними. Також еквівалентними в плані конвенції виклику є атрибути конвенції C і SYSCAL, але вони розрізняються конвенцією іменування.

Атрибут <видимість> визначає, чи буде підпрограма доступна (PUBLIC та EXPORT) для виклику з інших програм або модулів, чи не буде (PRIVATE). Останній атрибут <пролог> надає деякі можливості щодо керування генерацією асемблером коду прологу та епілогу підпрограми. Цей атрибут для 32-х розрядних додатків вважається застарілим.

<Регістри> визначає для директиви USES перелік розділених пробілом імен регістрів загального призначення, які будуть автоматично зберігатися на вході у підпрограму і поновлюватися на виході.

<Параметри> являють собою розділений комами перелік параметрів

підпрограми, що має синтаксис Параметр:тип параметру [, … [,\]]

Параметр символьне імя формального параметру підпрограми.

BYTE (SBYTE)

WORD (SWORD)

DWORD (SDWORD, REAL4)

тип параметру=

QWORD (REAL8)

визначений за допомогою TYPEDEF

VARARG

Для перенесення параметрів переліку на наступний рядок використовується символ «\» після коми.

Директива LOCAL дозволяє визначити локальні змінні для використання в підпрограмі. Память під локальні змінні резервується в стеку підпрограми і область їх видимості тільки код підпрограми. <Змінні> в директиві LOCAL являють собою розділений комами перелік, що має синтаксис

Змінна[[кількість]]:тип змінної [, ………………]

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

(але не масивів).

Змінна[кількість]:тип змінної для масивів з елементами простих та структурованих типів.

Соседние файлы в папке гос