МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”
/
Кафедра ЕОМ
Звіт
до лабораторної роботи № 7
з дисципліни
СТВОРЕННЯ DLL ТА ЇХ ВИКОРИСТАННЯ ПРИ ЯВНОМУ ЗВ’ЯЗУВАННІ НА МОВІ АСЕМБЛЕР
" Системне програмування "
Мета: Ознайомитись з технологією та оволодіти навиками створення та використання бібліотек динамічного компонування з використанням явного зв’язування на мові Асемблера.
ТЕОРЕТИЧНІ ВІДОМОСТІ
Динамічне компонування образу задачі в процесі її виконання надає ряд переваг розробникам програмного забезпечення в порівнянні зі статичним копонуванням. До переваг відносяться:
зменшується розмір виконуваного файлу;
у пам’ять завантажують лише одну копію динамічноїбібліотеки;
оновлення бібліотек не веде до перекомпонування застосування;
реалізовується динамічне завантаження модулів на вимогу;
можливість спільно використовувати ресурси застосування;
можна організувати спільну роботу бібліотек, розроблених із використанням різних мов програмування.
Однак воно не позбавлене недоліків:
сповільнює завантаження застосування;
не ефективно використовуватися зовнішня пам’ять;
проблема є зворотної сумісності;
ускладнюється процес інсталювання програмного застосування.
Однак грамонто володіючи технологією створення та підтримки динамічних бібліотек можне зменшити вплив деяких з цих недоліків на програмний продукт, а деякі подолати.
Можливі 2 способи використання динамічних бібліотек. Вони називаються “явним” та “неявним” зв’язуванням. “Явне” та “неявне” зв’язування бібліотеки з програмою мають суттєві відмінності в процесі написання та компіляції програми.
Неявне зв’язування бібліотеки з програмою (Load-time dynamic linking) полягає в тому, що бібліотека (яка міститься у файлі з розширенням .dll) завантажується в пам’ять в момент завантаження програми. До переваг “неявного” зв’язування в порівнянні з “явним” відноситься:
простота програмування. Розробник не вникає в проблеми зв’язування назв функцій з адресами за якими завантажена їх реалізація;
прогнозованість поведінки застосування. Якщо застосування успішно завантажено, то усі проблеми перехрестних зв’язків уже вирішено; Однак у “неявного” зв’язування існує ряд недоліків:
при відсутності бодай однієї з бібліотек при запуску програми відбудеться збій та припинення виконання програми;
значні затрати часу на завантаження та старт застосування, пов’язані з необхідністю завантаження усіх динамічних бібліотек;
відсутня можливість вивантаження непотрібних в даний час динамічних бібліотек;
на час компонування необхідно мати додаткові файли з прототипами функцій та бібліотеку імпорту (.lib).
Отже, основними перевагами “явного” зв’язування, є можливість тонко
керувати процесами завантаження та вивантаження динамічних бібліотек, а отже і використовуваною пам’яттю, хоча і за рахунок складності програмування.
“Явне” зв’язування бібліотеки з програмою (Run-time dynamic linking) полягає в тому, що бібліотека (яка міститься у файлі з розширенням .dll) завантажується в пам’ять в момент часу, що визначається розробником, за допомогою виклику АРІ функцій LoadLibrary або LoadLibraryEX. При успішному виконанні функція повертає адресу точки входу. При відсутності бібліотеки, яку необхідно завантажити, або при помилках її завантаження функція поверне NULL, а сама програма, може продовжити виконання. Звичайно, якщо функції, що містяться у відсутній бібліотеці не є критичними для її подальшої роботи.
Для виклику бібліотечної функції необхідно оголосити вказівник на функцію, та присвоїти йому адресу бібліотечної функції. Для цього необхідно використати АРІ функцію GetProcAddress, яка повертає адресу вказаної їй у параметрі бібліотечної функції.
Після завершення роботи з функціями бібліотек, програмі необхідно вивантажити бібліотеки за допомогою функції FreeLibrary.
Для успішної компіляції необхідно мати лише dll файл бібліотеки. Запуск програми відбудеться навіть за відсутності бібліотечного файлу, оскільки його наявність при використанні “явного” зв’язування не перевіряється.
Завдання
Створити DLL файл та здійснити явне зв*язування на мові Асемблер
ВАРІАНТИ ЗАВДАНЬ
Варіант №3
Знайти кількість слів у тексті, що починаються з заданої літери.
Лістинг програми:
First project: laba_7_3
main.asm
.586
.model flat,stdcall
option casemap:none
include D:\masm32\include\windows.inc
include D:\masm32\include\masm32.inc
include D:\masm32\include\debug.inc
include D:\masm32\include\kernel32.inc
include D:\masm32\include\user32.inc
include D:\masm32\include\gdi32.inc
includelib D:\masm32\lib\masm32.lib
includelib D:\masm32\lib\kernel32.lib
includelib D:\masm32\lib\user32.lib
includelib D:\masm32\lib\gdi32.lib
.data
LibName db "My_lib.dll",0
FuncName db "CharStartCounter",0
DLLNF db "DLL not found",0
AppName db "Load library",0
NotFound db "Function not found",0
mass db "School, Sky, Solution, Ann",0
cha db "S",0
.data?
hLib dd ?
LAB7Addr dd ?
.code
start:
invoke LoadLibrary, addr LibName
.if eax == NULL
invoke MessageBox,NULL,addr DLLNF,addr AppName,MB_OK
.else
mov hLib,eax
invoke GetProcAddress,hLib,addr FuncName
.if eax == NULL
invoke MessageBox,NULL,addr NotFound,addr AppName,MB_OK
.else
mov LAB7Addr,eax
push offset cha
push offset mass
call [LAB7Addr]
.endif
invoke FreeLibrary,hLib
.endif
invoke ExitProcess,NULL
end start
Second project: My_lib
My_dll.cpp
#include "my_dll_3.h"
extern "C" __declspec(dllexport) int CharStartCounter(char *mass, char *ID)
{
int count = 0;
bool beginWord = true;
for (int i = 0; i < strlen(mass); i++){
if (isalnum(mass[i])){
if (beginWord == false)
continue;
else if (beginWord == true && tolower(mass[i])==tolower(*ID)){
count++;
beginWord = false;
}
}
else if(isblank(mass[i])){
beginWord = true;
continue;
}
}
cout << "Words starting with letter " << ID << " are equal: " << count << endl;
return count;
}
My_dll_3.h
#ifndef _DLLTEST_H_
#define _DLLTEST_H_
#include <iostream>
using namespace std;
extern "C" __declspec(dllexport) int CharStartCounter(char* str, char *c);
#endif
Фото роботи програми:
/
Алгоритм виконання:
First project: laba_7_3
Ass.asm
На початку виконання програми відбувається підключення всіх необхідних бібліотек. У полі даних задаються змінні які будуть нести інформацію про те чи успішно все виконалось чи десь виникла помилка. Окремим блоком даних було виділено зміні які будуть містити адреси заголовку бібліотеки та функції.
invoke LoadLibrary, addr LibName за допомогою даної команди відбувається завантаження бібліотеки, якщо бібліотека була не успішна завантажена, то буде виведено відповідне повідомлення про помилку, якщо вдалось завантажити бібліотеку, то збережеться заголовок бібліотеки у змінній hLib. invoke GetProcAddress,hLib,addr FuncName – дана команда поверне вказівник на функцію яка зберігається у бібліотеці, якщо не вдасться взяти адресу функції, то буде видано відповідний ерор про дану помилку, якщо все-таки вдалось взяти адресу функції то буде здійснено занесення параметрів функції в стек за допомогою команд:
push offset cha
push offset mass
після чого буде здійснений виклик самої функції, коли функція буде виконана, то потрібно здійснити очистку пам*яті, invoke FreeLibrary,hLib – команда здійснює вивантаження з пам*яті бібліотеку, далі буде викликана функція яка завершить процес, і в самому кінці завершення програми.
Second project: My_lib
My_dll.cpp
У даному файлі описується безпосереднє виконання функції, яка буде шукати кількість
Слів які починаються із заданої букви, сам пошук здійснюється за наступним алгоритмом, задається зміна логічного типу(beginWord=true), після чого здійснюється вхід в цикл. Який виконується кількість разів яка рівна довжині стрічки, в цикля здійснюється ряд перевірок, перша перевірка перевіряє чи ми ввели символ, якщо так то перевіряється чи в нас початок слова, і даний символ рівний заданому, якщо так то відбувається інкремент змінної counter, а логічній змінній присвоюється 0, а якщо в нас змінна beginWord == false, то здійснюється продовження циклу, але вже з наступної ітерації. Друга перевірка полягає в тому, що якщо символ у нас рівний пробілу, то змінній beginWord присвоюється значення 1, і далі здійснюється перехід на наступну ітерацію.
My_dll_15.h
У даному хедері ми оголошуємо прототип функції у якої буде глобальне поле видимості, виконання програми призведе до утворення файлів які ми зможемо підключити до попереднього проекту, та використати дану функцію
Висновок: Ознайомилась з технологією та оволоділа навиками створення та використання бібліотек динамічного компонування з використанням явного зв’язування на мові асемблер.