Міністерство освіти і науки України
Національний університет «Львівська політехніка»
Звіт
Про виконання лабораторної роботи №2
«Структури даних для використання системних функцій»
Тема – структури даних для використання системних функцій.
Мета – навчитися будувати структури даних для використання функцій Win32API при програмуванні в операційній системі Windows.
ТЕОРЕТИЧНІ ПОЛОЖЕННЯ
Для використання більш складних функцій API необхідно використовувати спеціальні структури даних. Вся концепція програмування в WINDOWS основана на чіткому впорядкуванні структур даних, пов'язаних із ними програм-функцій та констант-параметрів. Структура це сукупність змінних, котрі об’єднані в один блок. Треба пам’ятати що структура в асемблері це логічне значення, насправді це масив значень (байтів), де кожен елемент структури займає конкретне місце у масиві.
Структури можуть розміщатися як в глобальній пам’яті (сегмент даних, виділена пам’ять), так і в локальній (сегмент стеку). В Асемблері є можливість визначити структуру як шаблон, і використовувати його як спеціальний тип даних, наприклад, тип SYSTEMTIME (опис структури взятий з файлу Windows.inc):
SYSTEMTIME STRUCT
WYear WORD ?
WMonth WORD ?
WDayOfWeek WORD ?
WDay WORD ?
WHour WORD ?
WMinute WORD ?
WSecond WORD ?
WMilliseconds WORD ?
SYSTEMTIME ENDS
Де WORD (dw) –довжина даних, 2 байти; а символ „?”, означає що по замовчуванню значення змінної невідоме, тобто буде залежати від сегмента в якому буде оголошена структура. Зауважте, що слово struct вказує на те, що данні реально не існують, а це ЛИШЕ ОПИС ШАБЛОНУ. Дані починають існувати коли оголошується змінна певного шаблонного типу, наприклад:
LOCAL Time: SYSTEMTIME
Де Time – це екземпляр структури, типу SYSTEMTIME. Зверніть увагу на слово LOCAL, котре вказує на те, що данні Є ЛОКАЛЬНИМИ, тобто знаходяться в сегменті стеку. Початково у локальних змінних вміст начення буде „сміття”, тобто данні, котрі були в стеці до виклику функції, в глобальних значення по замовчуванню.
Екземпляр структури, можна оголосити глобально. В сегменті даних:
.data? ; сегмент невизначених змінних
; змінна глобальна, початкові значення елементів „сміття”
;використовується якщо ми початково збираємось записати у структуру значення, а потім ;використовувати
Time SYSTEMTIME < ? >
.datа ; сегмент визначених змінних
; змінна глобальна, початкові значення елементів „0”.
Time SYSTEMTIME < 0 >
Для доступу до елементів екземпляру використовується крапка, так само як до записів в мові Pascal:
mov Time.wYear, 2006
Не забувайте що елементи екземпляру структури є адресою, тобто вказує на комірку пам‘яті, тому не можна робити запис з комірки в комірку на пряму !!!.
mov Time.wYear, Time. wMinute
Ця проблема вирішується за допомогою регістрів або стеку.
За допомогою регістрів :
mov ax, Time. wMinute
mov Time.wYear,ax
Ми використовуємо не розширений регістр eax (4 байти) а регістр ax (2 байти), тому що дані wMinute та wYear мають розмір 2 байти;
або за допомогою стеку :
push Time. wMinute
pop Time.wYear
Елементами таких структур можуть бути інші структури і т.д., в такому випадку для звернення до елементів використовується стільки крапок скільки існує рівнів структур.
Фактично існує два типа функцій API:
а) функції, які виконують будь-яку дію;
б) функції, які отримують будь-яку інформацію.
У даній лабораторній роботі треба отримати та розшифрувати одну з таких довідкових структур, яка містить інформацію про локальний час. Для виклику довільної довідкової функції необхідно вказати адресу місця в пам'яті, куди буде записана довідкова інформація. Цю адресу, як параметр функції, завжди перед викликом функції треба опустити в стек.
В лабораторній роботі необхідно також звернути увагу на те, що використовується унікальна АРІ функція wsprintf, котра не очищує стек (цей недолік виправлений у Windows XP). Це пов’язано з тим, що вона може містити не фіксовану кількість параметрів. В такому випадку програміст сам повинен вернути стек до попереднього стану. Для цього перед викликом треба зберегти регістр esp а потім повернути esp з деякої змінної (дивіться далі текст програми).
ПОРЯДОК ВИКОНАННЯ РОБОТИ
Запустити подану нижче програму, так як описано в попередній лабораторній роботі.
Додати до виводу значення секунд та мілісекунд.
Змінити текст програми таким чином, щоб функція API MessageBox виводила на екран вікно з двома кнопками: <OK> та <Cancel>. При натисненні кнопки <OK> програма повинна знову отримати локальний час, а при натисненні кнопки <Cancel> - програма завершує роботу. Для цього останнім параметром MessageBox, потрібно встановити константу MB_OKCANCEL. Тоді підпрограма (main) буде вертати відповідь користувача. Після повернення відповіді на верхній рівень, треба порівняти регістр EAX з константою IDOK, та знову виконати функцію (main) за допомогою послідовності команд (інструкцій):
cmp eax , IDOK ; порівняння регістра eax та константи IDOK
jz Begin ; якщо різниця цих значень = 0
або за допомогою макрокоманди .if:
.if eax == IDOK
jmp Begin
.endif
Оголошення всіх системних структур, констант та типів змінних, котрі використовуються для функцій АРІ заходяться у файлі Windows.inc. (прогляньте текстовим редактором цей файл).
Створити нові програми, котрі використовують наступні функції: GetSystemTime, DeleteFile, CopyFile, RemoveDirectory, SetCurrentDirectory, SetVolumeLabel, GetTempFileName, SetFileAttributes, GetFileAttributes, GetLogicalDrives, GetLogicalDriveStrings, MoveFile, FileTimeToLocalFileTime, SetFileTime, LocalFileTimeToFileTime, FindFirstFile, FindNextFile, FindClose.
Індивідуальне Завдання.
Видалити папку разом з файлами. Папку з файлами створити самостійно. Кількість файлів має перевищувати 3.
Код програми:
.586
.model flat,STDCALL
option casemap :none ;case sensitive
include Lab_3.inc
.code
Begin:
call main
invoke ExitProcess,NULL
main proc
invoke FindFirstFile,addr Dir, addr st1
mov hsearch,eax
l2: invoke FindNextFile,hsearch,addr st1
cmp eax,0
je l3
cmp st1.cFileName,'.'
jz l2
mov buff,0
invoke lstrcat,addr buff,addr Temp
invoke lstrcat,addr buff,addr st1.cFileName
invoke DeleteFile,addr buff
jmp l2
l3: invoke RemoveDirectory,addr Temp
invoke FindClose,hsearch
ret
main endp
end Begin
include WINDOWS.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
.data
Temp db "C:\lab\",0
Dir db "C:\lab\*.*",0
Time_title db 'Лабораторна робота 2',0
hsearch dd 0
st1 WIN32_FIND_DATA <0>
Ent db 13,10,0
Len dd 0
hFile dd 0
test1 dd 0
zm dd 0
.data?
b db 256 dup(?)
buff db 1000 dup(?)
buff2 db 1000 dup(?)
Висновок: виконуючи дану лабораторну роботу я навчився працювати з файлами та директоріями, а саме знаходити та видаляти їх. Вивчив як працюють функції FindFirstFile, FindNextFile, FindClose, DeleteFile та RemoveDirectory.