Лабораторна робота №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. (прогляньте текстовим редактором цей файл).
Текст програми
. ; Програма для визначення поточної дати та місцевого часу
include WINDOWS.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
.data ;Глобальнi данi
Time_title db ' Лабораторна робота №2',0
FORMAT_STRING \
db ' Системний час:',0dh,0ah,0dh,0ah
db ' Рiк: %ld',0dh,0ah
db ' Мiсяць: %d',0dh,0ah
db ' День тижня: %ld',0dh,0ah
db ' Число: %ld',0dh,0ah
db ' Година: %ld',0dh,0ah
db ' Хвилин: %ld',0dh,0ah
db 0 ;-кінець стрiчки
;0dh,0ah - код Enter(#13,#10)
;\ -перенос стрiчки
.data?
Save_esp dd ?
Lab_2.ASM.
.386
.model flat,STDCALL
option casemap :none ;case sensitive
include lab_2.inc
.code
Begin:
call main
invoke ExitProcess,NULL

main proc
LOCAL Time:SYSTEMTIME ;локальна змiнна,
;типу структура системного часу
LOCAL Buf[100]:BYTE ; локальний буфер в100 елементів
mov Save_esp,esp ; зберігаємо вказівник стеку
invoke GetLocalTime,addr Time;
xor eax,eax ; eax=0
mov ax,Time.wMinute
push eax
mov ax,Time.wHour
push eax
mov ax,Time.wDay
push eax
mov ax,Time.wDayOfWeek
push eax
mov ax,Time.wMonth
push eax
mov ax,Time.wYear
push eax
push offset FORMAT_STRING
lea eax,Buf
push eax
call wsprintf
mov esp, Save_esp; повертаємо вказівник стеку
invoke MessageBox,NULL,addr Buf,addr Time_title,MB_OK
ret
main endp
end Begin
Пояснення до програми:
Оскільки кожний елемент структури має розмір 2 байти, а параметри всіх Win32API функцій є 4-х байтні значення, ми мусимо привести всі потрібні нам дані до 4-х байтних величин. Тому спочатку очищуємо регістр eax, тобто онулюємо за допомогою логічної операції XOR (нагадати властивості логічних операцій). Записуємо у ax значення кожного елемента структури. Оскільки регістр ax є молодшою частиною eax а старша частина онулена, це означає еах приймає значення одного елемента структури. Ми можемо явно занести значення у стек, щоб не використовувати додаткові змінні для збереження значень, такий запис виглядає так:
...
mov ax,Time.wMinute
push eax
...
Пам’ятаємо що елементи як параметри функції, при явному завантажені у стек заносяться з кінця.
Після завантаження у стек всіх потрібних нам елементів структури, нам потрібно занести ще 2 параметри, адресу результуючого рядка, та адресу рядка формату. Оскільки рядок формати є глобальною зміною для взяття адреси використовуємо операцію offset і відразу заносимо у стек, цей запис виглядає так:

push offset FORMAT_STRING

Останнім параметром, що нам потрібно передати у стек, є адреса буферу повернення результату. Оскільки в нашому випадку буфер є локальною змінною, для взяття адреси нам потрібно використати команду Lea. У регістрі eax буде знаходитися адреса змінної Buf, цей параметр заносимо у стек, це виглядає так:
....
Lea eax, Buf
Push eax

Регістр може бути будь-яким, найчастіше це регістри edi,esi.
Створити нові програми, котрі використовують наступні функції: GetSystemTime, DeleteFile, CopyFile, RemoveDirectory, SetCurrentDirectory, SetVolumeLabel, GetTempFileName, SetFileAttributes, GetFileAttributes, GetLogicalDrives, GetLogicalDriveStrings, MoveFile, FileTimeToLocalFileTime, SetFileTime, LocalFileTimeToFileTime, FindFirstFile, FindNextFile, FindClose.
КОНТРОЛЬНІ ЗАПИТАННЯ
На які два основні типи поділяються функції API?
Що таке структура даних у Win32 API?
Чим відрізняється структура від її оголошення ?
Для чого існують структури даних?
Як передаються структури даних у системні функції?
Звідки беруться шаблони структур даних?
Що таке константа-параметр?
Де можна знайти перелік стандартних констант WINDOWS?
Чим і наскільки відрізняється місцевий час від системного?
Що таке файл?
Для чого використовуються тимчасові файли?
Що таке атрибут файлу?
Які ви знаєте функції для роботи з файлами та пристроями?
Що таке мітка диску?
Що таке поточний каталог?
Для чого потрібні тимчасові імена файлів і як їх отримати?
Що робить функція GetLogicalDriveStrings і чим вона відрізняється від функції GetLogicalDrives?
Індивідуальні Завдання.
Вивести інформацію о всіх логічних дисках комп’ютера, у одному вікні з іконкою інформації.
Вивести інформацію о всіх атрибутах файлу, у одному вікні з іконкою інформації та 2 кнопками «ОК» та «Cancel».При натисненні кнопки «ОК» повторити вивід повідомлення, при «Сancel» вийти з програми.
Видалити папку разом з файлами. Папку з файлами створити самостійно. Кількість файлі має перевищувати 3.
Вивести час та дату використовуючи функцію GetSystemTime.
Формат виводу:
Дата : 22 вересня 2007 рому
Час 17:05:35
Звернути увагу на часовий пояс.
Визначити атрибут файлу, якщо файл прихований та має мітку «тільки читання », зняти властивість «тільки читати» і стерти файл.
Визначити всі логічні диски та вивести їх мітки.
Скопіювати всі файли з папки. Папку задати або створити самому. Кількість файлі має перевищувати 3.
Витерти всі файли які були створені сьогоднішнім числом.
Встановити у всіх файлах вказаної папки властивість «прихований»
Написати програму яка після старту чекає 10 секунд і виводить повідомлення про час. Формат стрічки, наприклад:
Час запуску : 10:20:30
Час виводу повідомлення : 10:20:40
День тижня: понеділок
Дата виклику програми : 21 вересня 2007 року
Реалізувати пошук в директорії. Виводячи текстове повідомлення питати, чи потрібно змінити дату та час створення файлу. При підтверджені, тобто натисненні кнопки «ОК» змінити час та дату створення файлу, при натисненні «Cancel» продовжити пошук.
Пошук файлів по шаблону. Наприклад, по першим буквам, або його властивостях. Результат вивести у одному повідомлені.
Перевірити якщо файл має помітку «тільки читання» скопіювати його в якусь задану директорію.
Замінити ім’я файлу сьогоднішню датою та часом.
Формат, наприклад: 1.exe -> 22вересня2007(13:40).exe
Прив’язка до сьогоднішньої дати та часу.
Вивести вміст директорії в одному повідомлені. Кількість файлі має перевищувати 3.